最近項目需求,恰好要做一個時間軸,而iOS這方面時間軸的例子也比較少,我就把自己所做的例子和思路共享出來給大家,共同學習。
時間軸的具體實現效果如圖1所示:
圖1
第一步:看到這個圖,我們想到的第一反應就是使用tableView或者CollectionView來完成,那麼我這裡使用的是tableView。首先,創建一個Single View Application項目,在Main.Storyboard裡面拖入一個TableView(如圖2所示),這裡別忘記了把TableView的delegate指向ViewController。
圖 2
第二步:TableView完成了,接下來就是如何自定義TableViewCell了。在項目中new file選擇Cocoa Touch Class,然後選擇繼承自TableViewCell,然後勾選XIB file選項,命名為“TimeCourseTableViewCell”,點擊創建,完成後如圖3所示:
圖 3
接下來,就是為這個xib文件布局,通過圖4圈出來的,我們可以找出一個cell裡面具有什麼控件。
圖 4
根據這個,我們布局出來的如圖5所示,主要就是Label和View來完成布局。
圖 5
其實這裡肯定會有人有疑問:
1.為什麼下面那個不直接用一個Button就好了呢,還要用一個View裡面嵌套一個Label呢?
2.為什麼"內容"的那個label還要添加一個父控件View呢?
其實,剛開始的時候,我確實也是使用簡單的一個Button和一個Label以為就可以了。後來發現,莫名的出現明明設置了buttom和label的Frame,修改了Origin,卻總是出現亂七八糟的位置,後來通過view嵌套在裡面,改變view的位置,就完全可以實現了。這個BUG本人也不清楚,望知情人告知,謝謝。
第三步:接下來,看xib裡面的TimeCourseTableViewCell.h文件裡的代碼:
#import <UIKit/UIKit.h> @interface TimeCourseTableViewCell : UITableViewCell @property (weak, nonatomic) IBOutlet UILabel *lbDate; //日期 @property (weak, nonatomic) IBOutlet UILabel *lbTime; //時間 @property (weak, nonatomic) IBOutlet UIView *infoView; //白色底的那個View @property (weak, nonatomic) IBOutlet UILabel *lbInfoTitle; //通知標題 @property (weak, nonatomic) IBOutlet UILabel *lbInfoContent; //通知內容 @property (weak, nonatomic) IBOutlet UIView *infoContentView; //通知內容的父View @property (weak, nonatomic) IBOutlet UILabel *lbSegment; //豎著的灰色分割線 @property (weak, nonatomic) IBOutlet UIView *receiveView; //深紅色的View @property (weak, nonatomic) IBOutlet UILabel *lbReceive; //輕觸收到通知 - (CGFloat)setCellHeight:(NSString *)strInfo isSameDay:(BOOL)isSame; - (void)setRidues; - (void)setClick; - (void)setNotClick; @end
TimeCourseTableViewCell.m文件裡的代碼:
#import "TimeCourseTableViewCell.h" @implementation TimeCourseTableViewCell @synthesize lbDate; @synthesize lbTime; @synthesize infoView; @synthesize lbInfoTitle; @synthesize lbInfoContent; @synthesize lbReceive; @synthesize receiveView; @synthesize lbSegment; @synthesize infoContentView; - (void)awakeFromNib { // Initialization code } /*去掉上面的日期*/ - (void)deleteDate{ lbDate.hidden = YES; CGRect timeTemp = lbTime.frame; timeTemp.origin = CGPointMake(timeTemp.origin.x, 8); lbTime.frame = timeTemp; CGRect infoViewTemp = infoView.frame; infoViewTemp.origin = CGPointMake(infoViewTemp.origin.x, 8); infoView.frame = infoViewTemp; } /*設置顯示的文本高度,以確定整個tableViewCell的高度,最後返回cell高度*/ - (CGFloat)setCellHeight:(NSString *)strInfo isSameDay:(BOOL)isSame{ /*如果是同一天 則去掉上面的日期*/ if (isSame) { [self deleteDate]; } [lbInfoContent setNumberOfLines:0]; //0行,則表示根據文本長度,自動增加行數 NSString *labelText = strInfo; NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; [paragraphStyle setLineSpacing:5.0f];//調整行間距 [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])]; lbInfoContent.attributedText = attributedString; [lbInfoContent sizeToFit]; //填充 //NSLog(@"%@",lbInfoContent); CGRect infoContentViewTemp = infoContentView.frame; infoContentViewTemp.size = CGSizeMake(212, lbInfoContent.frame.size.height); infoContentView.frame = infoContentViewTemp; /*設置手勢點擊位置*/ CGRect btnTemp = receiveView.frame; btnTemp.origin = CGPointMake(0, infoContentView.frame.origin.y + infoContentView.frame.size.height + 8 ); receiveView.frame = btnTemp; //NSLog(@"%@",receiveView); /*設置整個infoView高度*/ CGRect viewTemp = infoView.frame; viewTemp.size = CGSizeMake(viewTemp.size.width, receiveView.frame.origin.y + receiveView.frame.size.height); infoView.frame = viewTemp; //NSLog(@"%@",infoView); lbSegment.frame = CGRectMake(lbSegment.frame.origin.x, 0, 3, infoView.frame.origin.y + infoView.frame.size.height + 8); NSLog(@"HEight %f",infoView.frame.origin.y + infoView.frame.size.height + 8); return infoView.frame.origin.y + infoView.frame.size.height + 8; } /*設置圓形*/ - (void)setRidues{ lbTime.layer.cornerRadius = lbTime.frame.size.width / 2; [lbTime.layer setMasksToBounds:YES]; } /*設置點擊閱讀樣式*/ - (void)setClick{ CGFloat R = (CGFloat) 128/255.0; CGFloat G = (CGFloat) 128/255.0; CGFloat B = (CGFloat) 128/255.0; CGFloat alpha = (CGFloat) 1.0; UIColor *ColorRGB = [ UIColor colorWithRed: R green: G blue: B alpha: alpha ]; receiveView.backgroundColor = ColorRGB; lbReceive.text = @"我已收到通知"; } /*設置未點擊閱讀樣式*/ - (void)setNotClick{ CGFloat R = (CGFloat) 255/255.0; CGFloat G = (CGFloat) 83/255.0; CGFloat B = (CGFloat) 83/255.0; CGFloat alpha = (CGFloat) 1.0; UIColor *ColorRGB = [ UIColor colorWithRed: R green: G blue: B alpha: alpha ]; receiveView.backgroundColor = ColorRGB; lbReceive.text = @"輕觸收到通知"; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } @end
接下來,看ViewController.m文件裡的代碼:
#import "ViewController.h" #import "TimeCourseTableViewCell.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UITableView *messageTableView; @property int messageSum; //cell個數 @property NSArray *infoArray; //保存信息內容 @property NSMutableArray *clickArray; //記錄是否已經閱讀了信息 1未接收 0接收 @end @implementation ViewController @synthesize messageSum; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. /*tableView*/ [self setTableViewStyle]; messageSum = 10; self.infoArray = [[NSArray alloc] initWithObjects:@"老夫聊發少年狂,治腎虧,不含糖。", @"錦帽貂裘,千騎用康王。", @"", @"為報傾城隨太守,三百年,九芝堂。酒酣胸膽尚開張,西瓜霜,喜之郎。", @"持節雲中,三金葡萄糖。會挽雕弓如滿月,西北望 ,阿迪王。", @"十年生死兩茫茫,恆源祥,羊羊羊。", @"千裡孤墳,洗衣用奇強。", @"縱使相逢應不識,補維C,施爾康。", @"夜來幽夢忽還鄉,學外語,新東方。相顧無言,洗洗更健康。得年年斷腸處,找工作,富士康", @"啦啦啦",nil]; self.clickArray = [[NSMutableArray alloc] initWithObjects:@"1", @"1", @"1", @"1", @"1", @"1", @"1", @"1", @"1", @"1",nil]; } #pragma mark - 設置messageTableView的背景色和去掉分割線 - (void)setTableViewStyle{ self.messageTableView.separatorStyle = UITableViewCellSeparatorStyleNone; //去掉tabelView分割線 CGFloat R = (CGFloat) 237/255.0; CGFloat G = (CGFloat) 237/255.0; CGFloat B = (CGFloat) 237/255.0; CGFloat alpha = (CGFloat) 1.0; UIColor *ColorRGB = [ UIColor colorWithRed: R green: G blue: B alpha: alpha ]; [self.messageTableView setBackgroundColor:ColorRGB]; } #pragma mark - TabelView數據源協議 //該方法指定了表格視圖的行數 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return messageSum; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ //按時間分組,假設這裡[0,2],[3,5],[6,9]是同一天 TimeCourseTableViewCell *nib = [[[NSBundle mainBundle] loadNibNamed:@"TimeCourseTableViewCell" owner:self options:nil] lastObject]; if ([indexPath row] == 0) { NSLog(@"0"); return [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:NO]; } else if ([indexPath row]<3) { NSLog(@"0 - 3"); return [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:YES]; }else if ([indexPath row] == 3){ NSLog(@"3"); return [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:NO]; }else if ([indexPath row] < 6){ NSLog(@"3 - 6"); NSLog(@"%f",[nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:YES]); return [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:YES]; }else if ([indexPath row] == 6){ NSLog(@"6"); NSLog(@"%f",[nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:NO]); return [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:NO]; }else if ([indexPath row] > 6){ NSLog(@"6- 9"); NSLog(@"%f",[nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:YES]); return [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:YES]; }else return 145; } //該方法返回單元格對象,有多少行表格,則調用多少次 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *simpleIdentify = @"TimeCourse"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleIdentify]; TimeCourseTableViewCell *nib = [[[NSBundle mainBundle] loadNibNamed:@"TimeCourseTableViewCell" owner:self options:nil] lastObject]; [nib setTag:[indexPath row]]; if ([[self.clickArray objectAtIndex:[indexPath row]] isEqualToString:@"1"]) { [nib setNotClick]; }else [nib setClick];
[nib setRidues]; UITapGestureRecognizer *Tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)]; nib.receiveView.userInteractionEnabled = YES; [nib.receiveView addGestureRecognizer:Tap]; if ([indexPath row] == 0) { [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:NO]; } else if ([indexPath row]<3) { [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:YES]; }else if ([indexPath row] == 3){ [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:NO]; }else if ([indexPath row] < 6){ [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:YES]; }else if ([indexPath row] == 6){ [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:NO]; }else if ([indexPath row] > 6){ [nib setCellHeight:[self.infoArray objectAtIndex:[indexPath row]] isSameDay:YES]; }
cell = nib; cell.selectionStyle = UITableViewCellSelectionStyleNone; //去掉提供的選中無顏色 return cell; } #pragma mark - TabelView代理協議 //選中事件 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"44"); } - (void)tapGesture:(UITapGestureRecognizer *)sender{ NSLog(@"接收通知"); UIView *view = sender.self.view; TimeCourseTableViewCell *cell = (TimeCourseTableViewCell *)view.superview.superview.superview; UILabel *lb = view.subviews[0]; NSString *str = @"輕觸收到通知"; if ([lb.text isEqualToString:str]) { [cell setClick]; [self.clickArray setObject:@"0" atIndexedSubscript:cell.tag]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
那麼,運行之後,效果如圖6所示:
圖 6
改一下顏色,完成如下:
至此,整個時間軸完成。
思路大概如下:
1.根據時間分組:判斷是不是同一天,如果是則把上面的日期隱藏,整體布局往上移動。
2.獲取點擊的是哪個cell:通過給cell添加tag,那麼我單擊手勢時候,便可以獲取出cell,然後更改這個cell的樣式
可能寫的不是很明白,大家可以認真看一下代碼。
源碼地址免費下載:http://download.csdn.net/detail/junlinfushi/8345531