您的位置:首页 > 移动开发 > IOS开发

iOS 时间轴相册 (配Demo下载)

2016-08-02 10:24 155 查看
iOS 照片时间轴下载地址http://download.csdn.net/detail/lovechris00/9592374
这两天看别人的时间轴效果,感觉有兴趣,不过代码不符合我的风格,就想自己重写一个,本以为一个小时就可以搞定,没想到写了三四个小时,在此分享,效果如下:



零、基本思路:

1、将日数据和月数据分别创建两个Model来方便传值:LineDayModel , LineMonthModel;

2、使用tableView展示数据,每一行的数据由一个模型决定:LineDisplayModel;

3、月份数据作为组头,每一组有多少行由每一天的照片占用的列数决定。

一、UI界面部分

1、创建tableView,并定义部分样式

- (UITableView *)tableView{
//    WS(weakSelf);
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 ;
}

//    NSLog(@"dayRows : %d",self.dayRows);

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) {
//                  NSLog(@"m : %d , n : %d , index : %d",m,n,m * 3 + n);
[pModel.imgArray addObject:self.imgArray[m * 3 + n]];
}

}

//        NSLog(@"pModel : %d , %@ , %@",pModel.isFirst,pModel.day,pModel.imgArray);

[self.displayArray addObject:pModel];
}

//    NSLog(@"该天行数 : %d",self.dayRows);

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];
//    [self.tableView reloadData];  //使用这种方法关闭不自然

}


本Demo实现的内容较少,还可以添加拍照上传、删除图片、查看大图等功能,欢迎大家丰富。

iOS 照片时间轴下载地址http://download.csdn.net/detail/lovechris00/9592374
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: