iOS 照片时间轴下载地址 : http://download.csdn.net/detail/lovechris00/9592374
这两天看别人的时间轴效果,感觉有兴趣,不过代码不符合我的风格,就想自己重写一个,本以为一个小时就可以搞定,没想到写了三四个小时,在此分享,效果如下:
零、基本思路:
1、将日数据和月数据分别创建两个Model来方便传值:LineDayModel , LineMonthModel;
2、使用tableView展示数据,每一行的数据由一个模型决定:LineDisplayModel;
3、月份数据作为组头,每一组有多少行由每一天的照片占用的列数决定。
一、UI界面部分
1、创建tableView,并定义部分样式
- - (UITableView *)tableView{
-
- if (!_tableView) {
-
- _tableView =[[UITableView alloc]initWithFrame:CGRectMake(0,0, kSCREEN_WIDTH, kSCREEN_HEIGHT) style: UITableViewStyleGrouped];
-
- _tableView.backgroundColor = [UIColor groupTableViewBackgroundColor];
-
- [_tableView registerNib:[TimeOneCell nib] forCellReuseIdentifier:cellTimeOne];
- [_tableView registerNib:[TimeTwoCell nib] forCellReuseIdentifier:cellTimeTwo];
-
- [_tableView setSeparatorColor:[UIColor lightGrayColor]];
- _tableView.tableFooterView = [UIView new];
- _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
-
- _tableView.delegate = self;
- _tableView.dataSource= self;
-
- [self.view addSubview:_tableView];
- }
- return _tableView;
- }
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
-
- return 86;
-
- }
-
- - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
-
- return 44;
- }
-
- - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
-
- return 20;
- }
2、自定义组头
继承自UIView,并添加Xib文件
3、自定义两种UITableViewCell
数据处理方法
- - (void)refreshUIWithImageArray:(NSArray *)array time:(NSString *)time
- {
- self.timeLabel.text = time;
-
- if (array.count > 0) {
- self.imgView1.image = [UIImage imageNamed:array[0]];
- }
-
- if (array.count > 1) {
- self.imgView2.image = [UIImage imageNamed:array[1]];
- }
-
- if (array.count > 2) {
- self.imgView3.image = [UIImage imageNamed:array[2]];
- }
- }
数据处理方法:
- - (void)refreshUIWithImageArray:(NSArray *)array
- {
- if (array.count > 0) {
- self.imgView1.image = [UIImage imageNamed:array[0]];
- }
-
- if (array.count > 1) {
- self.imgView2.image = [UIImage imageNamed:array[1]];
- }
-
- if (array.count > 2) {
- self.imgView3.image = [UIImage imageNamed:array[2]];
- }
- }
二、数据部分
1、创建LineDisplayModel 传递tableView每一行的数据;
其中,isFirst决定 是否为这个tableview的第一行(即显示日期的这一行),如下:
.h文件
- #import <Foundation/Foundation.h>
-
- @interface LineDisplayModel : NSObject
- @property (nonatomic,assign) BOOL isFirst;
- @property (nonatomic,copy) NSString *day;
- @property (nonatomic,strong) NSMutableArray *imgArray;
- @end
.m文件 不做任何数据处理
2、创建LineDayModel 接收每日的照片、日期;
其中,dayRow 用来计算本日照片占用多少行;如果0-3张照片,占用一行;4-6张照片,占用两行....
并把每一行的照片信息,赋值给LineDisplayModel,将displayModel组成displayArray
.h文件
- #import <Foundation/Foundation.h>
-
- @interface LineDayModel : NSObject
- @property (nonatomic,copy) NSString *day;
- @property (nonatomic,strong) NSArray *imgArray;
-
- @property (nonatomic,assign) int dayRows;
- @property (nonatomic,strong) NSMutableArray *displayArray;
-
- - (instancetype)initWithDay:(NSString *)day imgArray:(NSArray *)imgArray;
-
- @end
.m文件
- #import "LineDayModel.h"
- #import "LineDisplayModel.h"
-
- @implementation LineDayModel
- - (instancetype)initWithDay:(NSString *)day imgArray:(NSArray *)imgArray
- {
- self = [super init];
-
- self.day = day;
- self.imgArray = imgArray;
-
- self.dayRows = 0;
-
- if (self.imgArray.count % 3 != 0) {
- self.dayRows = self.imgArray.count / 3 + 1;
- }else{
- self.dayRows = self.imgArray.count / 3 ;
- }
-
-
-
-
- for (int m = 0; m < self.dayRows; m++) {
- LineDisplayModel *pModel = [[LineDisplayModel alloc]init];
- pModel.imgArray = [[NSMutableArray alloc]init];
-
- if (m == 0) {
- pModel.isFirst = YES;
- pModel.day = self.day;
- }else{
- pModel.isFirst = NO;
- pModel.day = @"";
- }
-
-
- for (int n = 0; n < 3; n++) {
-
-
- if (self.imgArray.count > m * 3 + n) {
-
- [pModel.imgArray addObject:self.imgArray[m * 3 + n]];
- }
-
- }
-
-
-
- [self.displayArray addObject:pModel];
- }
-
-
-
- return self;
- }
-
- -(NSMutableArray *)displayArray
- {
- if (!_displayArray) {
- _displayArray = [[NSMutableArray alloc]init];
- }
- return _displayArray;
- }
3、创建LineMonthModel 接收每月下面每日的信息汇总;
其中 days 作为接收 LineDayModel 的数组;
monthRows 将每日的行数加起来;
displayArray 将每日的 LineDisplayModel 加起来;
shouldOpen 决定在tableView上的开关状态;
.h文件:
- #import <Foundation/Foundation.h>
-
- @interface LineMonthModel : NSObject
-
- @property (nonatomic,copy) NSString *month;
- @property (nonatomic,strong) NSMutableArray *days;
- @property (nonatomic,assign) int monthRows;
- @property (nonatomic,assign) BOOL shouldOpen;
- @property (nonatomic,strong) NSMutableArray *displayArray;
-
- - (instancetype)initWithMonth:(NSString *)month days:(NSArray *)days;
-
- @end
.m文件
- #import "LineMonthModel.h"
- #import "LineDayModel.h"
- #import "LineDisplayModel.h"
-
- @implementation LineMonthModel
-
- - (instancetype)initWithMonth:(NSString *)month days:(NSArray *)days
- {
- self = [super init];
- self.month = month;
- self.days = [NSMutableArray arrayWithArray:days];
- self.monthRows = 0;
-
- self.displayArray = [[NSMutableArray alloc]init];
-
- for (int i = 0; i< self.days.count; i++) {
-
- LineDayModel *dModel = self.days[i];
- self.monthRows = self.monthRows + dModel.dayRows;
- [self.displayArray addObjectsFromArray:dModel.displayArray];
-
- }
-
- NSLog(@"该月行数 : %d , %@",self.monthRows,self.displayArray);
-
-
- return self;
- }
-
-
- -(NSMutableArray *)displayArray
- {
- if (!_displayArray) {
- _displayArray = [[NSMutableArray alloc]init];
- }
- return _displayArray;
- }
4、初始化照片、时间数据
在CSTimeLineViewController.h 中
将dataArray 作为成员变量,并接收所有的月份数据。
- - (void)initData{
-
- LineDayModel *lModel00 = [[LineDayModel alloc]initWithDay:@"5.1" imgArray:@[@"1",@"2"]];
- LineDayModel *lModel01 = [[LineDayModel alloc]initWithDay:@"5.2" imgArray:@[@"1",@"2",@"3",@"4",@"1"]];
- LineDayModel *lModel02 = [[LineDayModel alloc]initWithDay:@"5.3" imgArray:@[@"1",@"2",@"1"]];
-
- LineMonthModel *lmModel0 = [[LineMonthModel alloc]initWithMonth:@"2016年5月" days:@[lModel00,lModel01]];
-
-
- LineDayModel *lModel10 = [[LineDayModel alloc]initWithDay:@"6.1" imgArray:@[@"1",@"3",@"1"]];
- LineDayModel *lModel11 = [[LineDayModel alloc]initWithDay:@"6.2" imgArray:@[@"1",@"2",@"4"]];
-
-
- LineMonthModel *lmModel1 = [[LineMonthModel alloc]initWithMonth:@"2016年6月" days:@[lModel10,lModel11]];
-
-
- LineDayModel *lModel20 = [[LineDayModel alloc]initWithDay:@"7.1" imgArray:@[@"2",@"3",@"1",@"3",@"1"]];
- LineDayModel *lModel21 = [[LineDayModel alloc]initWithDay:@"7.2" imgArray:@[@"3",@"2",@"1",@"3",@"1",@"3",@"1",@"3",@"1"]];
-
- LineMonthModel *lmModel2 = [[LineMonthModel alloc]initWithMonth:@"2016年7月" days:@[lModel20,lModel21]];
-
- self.dataArray = [NSMutableArray arrayWithArray:@[lmModel0,lmModel1,lmModel2]];
-
- for (LineMonthModel *mModel in self.dataArray) {
- mModel.shouldOpen = YES;
- }
-
- NSLog(@"dataArray : %@",self.dataArray);
-
- }
5、tableView上的显示
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
-
- return self.dataArray.count;
- }
-
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
-
- LineMonthModel *mModel =self.dataArray[section];
-
- if (mModel.shouldOpen) {
- return mModel.monthRows;
- }
-
- return 0;
- }
-
-
- -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
- {
- TimeHeader *header = [[TimeHeader alloc]init];
-
- LineMonthModel *mModel =self.dataArray[section];
-
- header.timeLabel.text = mModel.month;
- header.btn.tag = section;
-
- if (mModel.shouldOpen) {
- [header.btn setTitle:@"关闭" forState:UIControlStateNormal];
-
- }else{
- [header.btn setTitle:@"打开" forState:UIControlStateNormal];
- }
-
- [header.btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
-
- return header;
- }
-
- - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
-
- UITableViewCell * cell;
-
- LineMonthModel *mModel =self.dataArray[indexPath.section];
- LineDisplayModel *dModel = mModel.displayArray[indexPath.row];
-
- NSLog(@"%@ isFirst : %d , imgArray : %@",dModel.day,dModel.isFirst,dModel.imgArray);
-
- if (dModel.isFirst) {
- TimeOneCell *tempCell = [tableView dequeueReusableCellWithIdentifier:cellTimeOne];
- [tempCell refreshUIWithImageArray:dModel.imgArray time:dModel.day];
- cell = tempCell;
-
- }else{
- TimeTwoCell *tempCell = [tableView dequeueReusableCellWithIdentifier:cellTimeTwo];
- [tempCell refreshUIWithImageArray:dModel.imgArray];
- cell = tempCell;
- }
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- return cell;
-
- }
6、打开/关闭该月份照片的控制
本来想直接使用[self.tableView reloadData]; 来重组数据,但是这样界面变化很难看;于是只刷新单组。
这里有很多动画效果,但是感觉UITableViewRowAnimationFade 和 UITableViewRowAnimationNone 最自然,使用UITableViewRowAnimationTop 和 UITableViewRowAnimationMiddle 会有卡顿的效果,同学们可以尝试下。
typedef NS_ENUM(NSInteger, UITableViewRowAnimation) {
UITableViewRowAnimationFade,
UITableViewRowAnimationRight, // slide in from right (or out to right)
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone, // available in iOS 3.0
UITableViewRowAnimationMiddle, // available in iOS 3.2. attempts to keep cell centered in the space it will/did occupy
UITableViewRowAnimationAutomatic = 100 // available in iOS 5.0. chooses an appropriate animation style for you
};
- - (void)btnAction:(UIButton *)sender{
-
- LineMonthModel *lmModel = self.dataArray[sender.tag];
- lmModel.shouldOpen = !lmModel.shouldOpen;
-
- [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:sender.tag] withRowAnimation:UITableViewRowAnimationFade];
-
-
- }
本Demo实现的内容较少,还可以添加拍照上传、删除图片、查看大图等功能,欢迎大家丰富。
iOS 照片时间轴下载地址 : http://download.csdn.net/detail/lovechris00/9592374