制作时间轴时最重要的是计算下一个圆点及时间轴的长度
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