本文共 5194 字,大约阅读时间需要 17 分钟。
上篇博客写了关于性能优化以及手工绘制自定义单元格内容,这篇我们利用TableView的Section的Header来实现类似QQ好友列表的效果。
TableView有一个代理方法
这个方法返回一个UIView对象,我们可以将一个Button对象设为这个Section的Header,在点击它的时候展开列表内容。
简单地看下假的好友列表数据
一个array中包含多个dictionary,字典中又包括组别的名字以及好友列表,好友也用一个字典来表示,分别有名称,是否在线以及头像图片名字。
加载数据
01.
- (
void
)loadData
02.
{
03.
NSString *path = [[NSBundle mainBundle] pathForResource:@
"friends"
ofType:@
"plist"
];
04.
_dataList = [NSArray arrayWithContentsOfFile:path];
05.
_headers = [NSMutableDictionary dictionaryWithCapacity:_dataList.count];
06.
07.
_groupNames = [NSMutableArray arrayWithCapacity:_dataList.count];
08.
for
(NSInteger i = 0; i < _dataList.count; i++)
09.
{
10.
NSDictionary *dict = _dataList[i];
11.
[_groupNames addObject:dict[@
"groupname"
]];
12.
}
13.
}
之后我们开始写一个自定义的头部按钮来方便我们想要的布局
01.
- (id)initWithFrame:(CGRect)frame
02.
{
03.
self = [super initWithFrame:frame];
04.
if
(self) {
05.
UIImage *image = [UIImage imageNamed:@
"arrow-right"
];
06.
[self setImage:image forState:UIControlStateNormal];
07.
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
08.
//[self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
09.
_open = NO;
10.
}
11.
return
self;
12.
}
13.
14.
- (
void
)setOpen:(
BOOL
)open
15.
{
16.
_open = open;
17.
//设定点击旋转动画效果
18.
[UIView beginAnimations:nil context:nil];
19.
self.imageView.transform = CGAffineTransformMakeRotation(self.isOpen?M_PI_2:0);
20.
[UIView commitAnimations];
21.
}
有一个BOOL型的成员_open来记录button是否被点击的状态,在点击时,左侧的图片有一个短暂的旋转动画效果。
然后设置图片以及标题的位置
01.
//图像显示位置
02.
- (CGRect)imageRectForContentRect:(CGRect)contentRect
03.
{
04.
return
CGRectMake(RMarginX, RMarginY, RIconSide, RIconSide);
05.
}
06.
07.
//标题显示位置
08.
- (CGRect)titleRectForContentRect:(CGRect)contentRect
09.
{
10.
return
CGRectMake(RIconSide + 4*RMarginX, 0, contentRect.size.width, contentRect.size.height);
11.
}
在drawRect中还绘制了底部的分割线以及光泽,不过由于背景没有绘制渐变,光泽效果有些突兀。
绘制底边
01.
CGContextRef context = UIGraphicsGetCurrentContext();
02.
03.
CGContextSaveGState(context);
04.
CGContextSetStrokeColorWithColor(context, [UIColor darkGrayColor].CGColor);
05.
CGContextMoveToPoint(context,
0
, rect.size.height);
06.
CGContextAddLineToPoint(context,
320
, rect.size.height);
07.
CGContextSetLineWidth(context,
2
.0f);
08.
CGContextStrokePath(context);
09.
CGContextRestoreGState(context);
然后是光泽效果
01.
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
02.
UIColor *light = [UIColor colorWithRed:
1.0
green:
1.0
blue:
1.0
alpha:
0.1
];
03.
UIColor *dark = [UIColor colorWithRed:
1.0
green:
1.0
blue:
1.0
alpha:
0.35
];
04.
NSArray *colors = @[(__bridge id)light.CGColor, (__bridge id)dark.CGColor];
05.
CGFloat locations[] = {
0.0
,
1.0
};
06.
07.
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);
08.
09.
CGContextSaveGState(context);
10.
CGPoint start = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
11.
CGPoint end = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
12.
CGContextDrawLinearGradient(context, gradient, start, end,
0
);
13.
14.
CGColorSpaceRelease(colorSpace);
15.
CGGradientRelease(gradient);
16.
CGContextRestoreGState(context);
接着我们还需要自定义一个单元格类来接受和绘制数据,
具体实现类似于上篇博客中介绍的手工绘制单元格的内容
这里只看数据绑定的部分
1.
- (
void
)bindFriend:(NSDictionary *)myFriend
2.
{
3.
_name = myFriend[@
"name"
];
4.
_online = [myFriend[@
"isonline"
] boolValue];
5.
_headerImage = [UIImage imageNamed:myFriend[@
"imagename"
]];
6.
7.
[self setNeedsDisplay];
8.
}
在完成头部绘制以及单元格绘制的准备后,我们就可以在控制器中实现代理方法,讲数据排版到界面上了。
显示头部视图
01.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
02.
{
03.
HeaderButton *header = _headers[@(section)];
04.
if
(!header)
05.
{
06.
header = [HeaderButton buttonWithType:UIButtonTypeCustom];
07.
header.bounds = CGRectMake(0, 0, 320, RHeaderHeight);
08.
header.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.8 alpha:1.0];
09.
header.titleLabel.font = [UIFont systemFontOfSize:16.0f];
10.
NSString *title = _groupNames[section];
11.
[header setTitle:title forState:UIControlStateNormal];
12.
[header addTarget:self action:@selector(expandFriends:) forControlEvents:UIControlEventTouchUpInside];
13.
[_headers setObject:header forKey:@(section)];
14.
}
15.
return
header;
16.
}
头部点击的监听方法
1.
- (
void
)expandFriends:(HeaderButton *)header
2.
{
3.
header.open = !header.isOpen;
4.
[self.tableView reloadData];
5.
}
点击的时候改变header的_open值,然后刷新视图内容。
根据header的_open来确定是否显示section中的列表
1.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
2.
{
3.
HeaderButton *header = _headers[@(section)];
4.
NSArray *array = [self arrayWithSection:section];
5.
NSInteger count = header.isOpen?array.count:0;
6.
return
count;
7.
}
绑定数据并且显示单元格
01.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
02.
{
03.
HRFriendsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
04.
05.
NSArray *array = [self arrayWithSection:indexPath.section];
06.
[cell bindFriend:array[indexPath.row]];
07.
08.
return
cell;
09.
}
这样我们的工作几乎就完成了,下面来看一下效果图
转载地址:http://cmqgi.baihongyu.com/