现在很多的iOS应用都是有瀑布流的设计的,今天我要介绍的是整齐的那种,也就是说瀑布流中的每张图片的大小都是一样的瀑布,这样的板式在壁纸这些应用中时会用到。等高的图片,可以用表格来实现。 表格能实现单元格的重用,优化内存,能实现scrollview的一些代理方法(有点废话),这些都是一些重要的特征,之后所要讲的都是和这些有关。
我们现在来逐步的分解实现瀑布流的步骤:
1.创建表格,为了简单起见,我把表格的delegate和dataSource都由当前的视图控制器来实现。
- (void)viewDidLoad
{
[super viewDidLoad];
//创建表格
self.tableView = [UITableView alloc] initWithFrame:CGRectMake(0,44,320,416)];
self.view.backgroundColor = [UIColor colorWithRed:0.945 green:0.945 blue:0.945 alpha:1];
tableView.decelerationRate = UIScrollViewDecelerationRateNormal;
self.tableView.backgroundColor = [UIColor colorWithRed:0.945 green:0.945 blue:0.945 alpha:1];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
tableView.delegate =self;
tableView.dataSource = self;
//datas中的数据是我们瀑布流中用的图片
datas = [NSArray alloc]initWithObjects:@"http://ww2.sinaimg.cn/bmiddle/7c2e6fffjw1dv4wr3zksfj.jpg",
@"http://ww3.sinaimg.cn/bmiddle/5375ccc8gw1dv5i4huekzj.jpg",
@"http://ww4.sinaimg.cn/bmiddle/69841610jw1dv5i0ybyazj.jpg",
@"http://ww1.sinaimg.cn/bmiddle/7fbd5c93gw1dv4xm1wou3j.jpg",
@"http://ww4.sinaimg.cn/bmiddle/6241c35cjw1dv5gh08z16j.jpg",
@"http://ww1.sinaimg.cn/bmiddle/84328014jw1dv4lm8niqej.jpg",
@"http://ww1.sinaimg.cn/bmiddle/4726cd59gw1dv5imx1hlaj.jpg",
@"http://ww4.sinaimg.cn/bmiddle/4701280btw1dv5dbnhawjj.jpg",
@"http://ww2.sinaimg.cn/bmiddle/46e7ba41gw1dv5ivrhmjxj.jpg",
nil];
//添加到上方的刷新的EGORefreshView
if (!_refreshHeadView) {
EGORefreshTableHeaderView *view = [[EGORefreshTableHeaderView alloc]initWithFrame:CGRectMake(0, 0.0f-tableView.bounds.size.height, tableView.bounds.size.width, tableView.bounds.size.height)];
view.delegate = self;
[tableView addSubview:view];
_refreshHeadView = view;
[view release];
headScrollView.delegate = self;
[headScrollView setContentSize:CGSizeMake(320, 40)];
}
}
2,实现表格的delegate 和dataSource
下面这个代理函数我就不介绍了。
– (NSInteger)numberOfSectionsInTableView
{
return 1;
}
这个代理是用来描述表格的行数的,我们现在是要建立三列的瀑布流,所有我用的是 ceil([datas count]/3),同理,你要建立N列的瀑布流,你只要把3替换成N就行了。
–(NSInteger) tableView:numberOfRowsInSection
{
return ceil([datas count]/3);
}
我们来实现最关键的代理,
- (UITableViewCell*)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
StatusCell *statusCell = (StatusCell*)[aTableView dequeueReusableCellWithIdentifier:CellIdentifierText];
if (statusCell == nil)
{
statusCell = [[[StatusCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierText]autorelease];
}
NSArray *subArray = [datas subarrayWithRange:NSRangeMake(indexPath.row*3 ,3)];
[self configCellWithArray:subArray];
cell =statusCell;
return cell;
}
3 ,代理完成了,这个时候我要来分解下继承UITableViewCell的StatusCel这个类的函数:- (void)configCellWithArray:(NSArray*)array;
-(void)configureCellWithArray:(NSArray*)array
{
int nCount = [array count];
NSArray *array = [self.contentView subviews];
for (UIView *view in array) {
[view removeFromSuperview];
}
UIImage *defaultImage=nil; //用于单个图片的视图的默认图片,可以为空
//构建单元格的视图区域
for(int index = 0;index < nCount; index ++ )
{
NSString *url = [array objectAtIndex:index];
CGRect frame = CGRectMake(originPoint.x + (index*(viewSize.width+viewDistance)), originPoint.y, viewSize.width, viewSize.height);
//
ContentCellView *cellView = [[ContentCellView alloc]initWithPlaceholderImage:defaultImage];
cellView.statusGroup = stautsGroup;
[cellView setImageURL:url];
[cellView setFrame:frame];
[self.contentView addSubview:cellView];
[cellView release];
}
}
这里边有几个要点
(1) 每次操作把当前的单元格的子视图移除掉是很关键的,很明朗但是很关键,容易忽略掉
(2)ContentCellView是我重写的一个UIImageView 的子类,主要是为了定制显示图片的行为。setImageURL,是一个异步处理的动作,具体这个函数式如何实现的,我们今天不讨论了,这个函数的灵活性体现在你可以在这个函数中加UIAcitivityIndicator 来增加等待,可以在下载完成之前加入默认图片,总之是非常的灵活的。
(3) CGRect frame = CGRectMake(originPoint.x + (index*(viewSize.width+viewDistance)), originPoint.y, viewSize.width, viewSize.height); 这一行中的 originPoint,viewSize,ViewDistance 是根据不同的列数来定制不同的单元格中的单个视图的大小和它们相互之间的间距。
四 .总结和注意点:
UITableView的用法是非常的灵活的,其中还有很多的代理方法我们没有用到。在定制StatusCell的时候有layOutSubView和drawRect这个两个方法是我没用来定制的,为何呢?一个很重要的原因是它们作为一个系统方法,覆盖它们的时候不知道他们何时去执行是很危险的,同时不断的drawRect开销也是比较大的.