制作时间轴时最重要的是计算下一个圆点及时间轴的长度
1.计算高度可以按取出的当前模型的内容计算,如下:
//取出的每个模型
GTimeLineViewModel *timeLimeM = dataArray[i];
//设置内容
NSString *content = timeLimeM.text;
//计算高度,注意这里的宽度很关键,将会控制你文字设置的高度,options设置为:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
CGSize size = [content boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} context:nil].size;
2.当计算下一个圆圈的y值时,算法如下:
- (CGFloat)iyToDataArray:(NSArray <GTimeLineViewModel *> *)dataArray toIndex:(NSInteger)index{
CGFloat iy = 0;
GTimeLineViewModel *viewModel;
if (index > 0) {
CGFloat contentH = 0;
//计算下一个圆圈,关键点就在这里,当i=1公式为上一个的圆圈+上一个时间轴的高度,当i //== 2时公式为:
//(i- 1)+(i - 2)内容的高度,当i == 3时公式为:
//(i- 1)+(i - 2)+(i-3)内容的高度等等。
for (NSInteger i = index; i > 0; i--) {
viewModel= [dataArray objectAtIndex:(i-1)];
NSString *content = viewModel.text;
CGSize size = [content boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[self FontSizeHeight:14]} context:nil].size;
contentH = contentH+size.height;
}
// CGFloat textH = [self compareHeigth:contentH];
iy = index * (KTIMELINEAUX_WH_CIRCLE+ 2*[_ktimeLineAux kTimeLineAuxScaleHeight:KTIMELINEAUX_HGAP_CIRCLE_IMAGE]+KTIMELINEAUX_WGAP_LEFT)+contentH;
}else{//为0时,y值 就是0
viewModel = dataArray[index];
NSString *content = viewModel.text;
CGSize size = [content boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[self FontSizeHeight:14]} context:nil].size;
iy = index * (KTIMELINEAUX_WH_CIRCLE+size.height+ 2*[_ktimeLineAux kTimeLineAuxScaleHeight:KTIMELINEAUX_HGAP_CIRCLE_IMAGE]+KTIMELINEAUX_WGAP_LEFT);
}
return iy;
}
3.下面就时间轴制作的整套代码
#define TIME_SCERRN_WIDTH [UIScreen mainScreen].bounds.size.width
#define TIME_SCERRN_HEIGHT [UIScreen mainScreen].bounds.size.height
#import "GTimeLineView.h"
#import "GTimeLineViewModel.h"
#import "KTimeLineAux.h"
#import "UIImage+Custom.h"
@interface GTimeLineView(){
UILabel *_circleL; //圆圈
UILabel *_lineL; //竖线
UILabel *_twoCircleL; //圆圈2
UILabel *_timeL; //时间label
UIImageView *_conentImageV; //存储label文字
UILabel *_conentL; //label文字
KTimeLineAux *_ktimeLineAux;
}
@end
@implementation GTimeLineView
- (void)timeLineViewWithFrame:(CGRect)frame reloadDataWithArray:(NSArray<GTimeLineViewModel *> *)dataArray{
if (dataArray && dataArray.count > 0) {
[self loadUI:frame];
for (NSInteger i = 0; i < dataArray.count; i++) {
id sub = dataArray[i];
if (![sub isKindOfClass:[GTimeLineViewModel class]]) {
return;
}
GTimeLineViewModel *timeLimeM = dataArray[i];
NSString *content = timeLimeM.text;
if (!content.length) {
return;
}
CGFloat imageW = [self getImageViewWidth];
CGSize size = [content boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} context:nil].size;
//线的高度
CGFloat lineHeight = 2*[_ktimeLineAux kTimeLineAuxScaleHeight:KTIMELINEAUX_HGAP_CIRCLE_IMAGE]+size.height+KTIMELINEAUX_WGAP_LEFT;
CGFloat circleY = [self iyToDataArray:dataArray toIndex:i];
[self setFrame:frame];
//one circle
_circleL = [[UILabel alloc] initWithFrame:CGRectMake(frame.origin.x,circleY,KTIMELINEAUX_WH_CIRCLE, KTIMELINEAUX_WH_CIRCLE)];
[self setCornerRadiusWithLabel:_circleL];
_circleL.layer.borderColor = [self sixtyTwoColor].CGColor;
_circleL.layer.borderWidth = 2;
//line
_lineL = [[UILabel alloc] initWithFrame:CGRectMake(_circleL.center.x-KTIMELINEAUX_WIDTH_LINE/2,CGRectGetMaxY(_circleL.frame),KTIMELINEAUX_WIDTH_LINE,lineHeight)];
[_lineL setBackgroundColor:[self sixtyTwoColor]];
//time
_timeL = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(_circleL.frame)+[_ktimeLineAux kTimeLineAuxScaleWidth:KTIMELINEAUX_WGAP_CIRCLE_TIME],CGRectGetMinY(_circleL.frame)-2,KTIMELINEAUX_WIDTH_TIME_LABEL,KTIMELINEAUX_HEIGHT_TIME_LABEL)];
[_timeL setTextColor:[self sixtyTwoColor]];
_timeL.text = timeLimeM.time;
[_timeL setFont:[self FontSizeHeight:16]];
_timeL.textAlignment = NSTextAlignmentLeft;
//image
_conentImageV = [[UIImageView alloc] initWithFrame:CGRectMake([_ktimeLineAux kTimeLineAuxScaleWidth:KTIMELINEAUX_WGAP_IMAGE_LEFT],CGRectGetMaxY(_circleL.frame)+[_ktimeLineAux kTimeLineAuxScaleHeight:KTIMELINEAUX_HGAP_CIRCLE_IMAGE],imageW,size.height+10)];
_conentImageV.image = [UIImage resizeableImageWithName:@"timeImage"];
_conentL = [[UILabel alloc] initWithFrame:CGRectMake(KTIMELINEAUX_WGAP_LEFT, KTIMELINEAUX_WGAP_LEFT,CGRectGetWidth(_conentImageV.frame)-2*KTIMELINEAUX_WGAP_LEFT, size.height)];
_conentL.numberOfLines = 0;
_conentL.lineBreakMode = NSLineBreakByCharWrapping;
_conentL.text = content;
[_conentL setTextColor:[self fivtyOneColor]];
[_conentImageV addSubview:_conentL];
if (i == dataArray.count -1) {
_twoCircleL = [[UILabel alloc] initWithFrame:CGRectMake(frame.origin.x,CGRectGetMaxY(_lineL.frame),KTIMELINEAUX_WH_CIRCLE, KTIMELINEAUX_WH_CIRCLE)];
[self setCornerRadiusWithLabel:_twoCircleL];
_twoCircleL.layer.borderColor = [self sixtyTwoColor].CGColor;
_twoCircleL.layer.borderWidth = 2;
[_twoCircleL setBackgroundColor:[UIColor clearColor]];
//change Frame
CGRect selfF = self.frame;
selfF.size.height = CGRectGetMaxY(_twoCircleL.frame)+10;
self.frame = selfF;
// [self setContentSize:CGSizeMake(frame.size.width,3000)];
}
// [_scrollView addSubview:self];
[self addSubview:_circleL];
[self addSubview:_lineL];
[self addSubview:_twoCircleL];
[self addSubview:_timeL];
[self addSubview:_conentImageV];
[self addSubview:_twoCircleL];
NSLog(@"
_circleL= %@
_lineL =%@
_timeL=%@
_conentImageV=%@
_twoCircleL=%@
self=%@
",_circleL,_lineL,_timeL,_conentImageV,_twoCircleL,self);
}
}
}
#pragma mark --- loadUI
- (void)loadUI:(CGRect)frame{
_ktimeLineAux = [KTimeLineAux shareTimeLineAux];
CGFloat iy = 0;
if (frame.size.height <TIME_SCERRN_HEIGHT) {
iy = TIME_SCERRN_HEIGHT;
}else{
iy = frame.size.height;
}
}
#pragma mark --- font
- (UIFont*)FontSizeHeight:(CGFloat)height{
return [UIFont systemFontOfSize:height];
}
#pragma mark --- Radius
- (void)setCornerRadiusWithLabel:(UILabel *)label{
label.layer.cornerRadius = KTIMELINEAUX_WH_CIRCLE/2;
label.layer.masksToBounds = YES;
}
#pragma mark --- color
- (UIColor *)fivtyOneColor{
return [self colorWithR:51 G:51 B:51];
}
- (UIColor *)sixtyTwoColor{
return [self colorWithR:62 G:147 B:75];
}
- (UIColor *)colorWithR:(CGFloat)r G:(CGFloat)g B:(CGFloat)b{
return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0];
}
//_circly iy
- (CGFloat)iyToDataArray:(NSArray <GTimeLineViewModel *> *)dataArray toIndex:(NSInteger)index{
CGFloat iy = 0;
GTimeLineViewModel *viewModel;
if (index > 0) {
CGFloat contentH = 0;
for (NSInteger i = index; i > 0; i--) {
viewModel= [dataArray objectAtIndex:(i-1)];
NSString *content = viewModel.text;
CGSize size = [content boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[self FontSizeHeight:14]} context:nil].size;
contentH = contentH+size.height;
}
// CGFloat textH = [self compareHeigth:contentH];
iy = index * (KTIMELINEAUX_WH_CIRCLE+ 2*[_ktimeLineAux kTimeLineAuxScaleHeight:KTIMELINEAUX_HGAP_CIRCLE_IMAGE]+KTIMELINEAUX_WGAP_LEFT)+contentH;
}else{
viewModel = dataArray[index];
NSString *content = viewModel.text;
CGSize size = [content boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[self FontSizeHeight:14]} context:nil].size;
iy = index * (KTIMELINEAUX_WH_CIRCLE+size.height+ 2*[_ktimeLineAux kTimeLineAuxScaleHeight:KTIMELINEAUX_HGAP_CIRCLE_IMAGE]+KTIMELINEAUX_WGAP_LEFT);
}
return iy;
}
- (CGFloat)getImageViewWidth{
return (TIME_SCERRN_WIDTH - [_ktimeLineAux kTimeLineAuxScaleWidth:KTIMELINEAUX_WGAP_IMAGE_LEFT] - 2*KTIMELINEAUX_WGAP_RIGHT);
}
- (CGFloat)compareHeigth:(CGFloat)height{
CGFloat h = 30;
if (h > height)
return h;
else
return height;
}
@end
+ (UIImage *)resizeableImageWithName:(NSString *)name{
UIImage *image = [UIImage imageNamed:name];
NSInteger leftCapWidth = image.size.width *0.7;
NSInteger topCapHeight = image.size.height *0.5;
CGFloat left = 5;
CGFloat right = 10;
CGFloat top = 10;
CGFloat bottom = 10;
UIEdgeInsets insets = UIEdgeInsetsMake(top, left, bottom, right);
return [image resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch];
// return [image stretchableImageWithLeftCapWidth:leftCapWidth topCapHeight:topCapHeight];
}
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface KTimeLineAux : NSObject
extern const NSInteger KTIMELINEAUX_WIDTH_TIME_LABEL; //时间的宽度
extern const NSInteger KTIMELINEAUX_WIDTH_LINE; //线的宽度
extern const NSInteger KTIMELINEAUX_WH_CIRCLE; //圆圈的大小
extern const NSInteger KTIMELINEAUX_HEIGHT_TIME_LABEL; //时间的高度
extern const NSInteger KTIMELINEAUX_WGAP_LEFT; //视图左边间距
extern const NSInteger KTIMELINEAUX_WGAP_RIGHT; //视图右边间距
extern const NSInteger KTIMELINEAUX_HGAP_CIRCLE_IMAGE; //圆圈与存储文字的视图的上下间距
extern const NSInteger KTIMELINEAUX_WGAP_CIRCLE_TIME; //圆圈与时间label的间距
extern const NSInteger KTIMELINEAUX_WGAP_LINE_IMAGE; //线与存储文字视图的左右间距
extern const NSInteger KTIMELINEAUX_WGAP_IMAGE_LEFT; //存储文字视图左边间距
extern const NSInteger KTIMELINEAUX_WGAP_IMAGE_RIGHT; //存储文字视图右边间距
+ (KTimeLineAux *)shareTimeLineAux;
/**按比例获取高度*/
- (CGFloat)kTimeLineAuxScaleHeight:(CGFloat)height;
/**按比例获取宽度*/
- (CGFloat)kTimeLineAuxScaleWidth:(CGFloat)width;
@end
#define SCREEN_WIDTH ([[UIScreen mainScreen]bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen]bounds].size.height)
#define SCREEN_WIDTH_SCALE SCREEN_WIDTH/375
#define SCREEN_HEIGHT_SCALE SCREEN_HEIGHT/667
#define SCREEN_DEFAULT_HEIGHT 667
#import "KTimeLineAux.h"
@implementation KTimeLineAux
NSInteger const KTIMELINEAUX_WIDTH_TIME_LABEL = 100;
NSInteger const KTIMELINEAUX_HEIGHT_TIME_LABEL = 20;
NSInteger const KTIMELINEAUX_WIDTH_LINE = 2;
NSInteger const KTIMELINEAUX_WH_CIRCLE = 8;
NSInteger const KTIMELINEAUX_HGAP_CIRCLE_IMAGE = 17;
NSInteger const KTIMELINEAUX_WGAP_LEFT = 10;
NSInteger const KTIMELINEAUX_WGAP_RIGHT = 10;
NSInteger const KTIMELINEAUX_WGAP_CIRCLE_TIME = 19;
NSInteger const KTIMELINEAUX_WGAP_IMAGE_LEFT = 33;
NSInteger const KTIMELINEAUX_WGAP_IMAGE_RIGHT = 10;
+ (KTimeLineAux *)shareTimeLineAux{
static KTimeLineAux *timeLine = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
timeLine = [[KTimeLineAux alloc] init];
});
return timeLine;
}
- (CGFloat)kTimeLineAuxScaleHeight:(CGFloat)height{
if (height<=0) {
return 0;
}
CGFloat scaleH = height*SCREEN_HEIGHT_SCALE;
return scaleH;
}
- (CGFloat)kTimeLineAuxScaleWidth:(CGFloat)width{
if (width <= 0) {
return 0;
}
CGFloat scaleW = width*SCREEN_WIDTH_SCALE;
return scaleW;
}
@end