MyException - 我的异常网
当前位置:我的异常网» 移动开发 » 详解TableView —— QQ挚友列表的实现

详解TableView —— QQ挚友列表的实现

www.MyException.Cn  网友分享于:2013-10-09  浏览:70次
详解TableView —— QQ好友列表的实现


上篇博客写了关于性能优化以及手工绘制自定义单元格内容,这篇我们利用TableView的Section的Header来实现类似QQ好友列表的效果。


TableView有一个代理方法


这个方法返回一个UIView对象,我们可以将一个Button对象设为这个Section的Header,在点击它的时候展开列表内容。


简单地看下假的好友列表数据




一个array中包含多个dictionary,字典中又包括组别的名字以及好友列表,好友也用一个字典来表示,分别有名称,是否在线以及头像图片名字。


加载数据


- (void)loadData
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"friends" ofType:@"plist"];
    _dataList = [NSArray arrayWithContentsOfFile:path];
    _headers = [NSMutableDictionary dictionaryWithCapacity:_dataList.count];
    
    _groupNames = [NSMutableArray arrayWithCapacity:_dataList.count];
    for (NSInteger i = 0; i < _dataList.count; i++)
    {
        NSDictionary *dict = _dataList[i];
        [_groupNames addObject:dict[@"groupname"]];
    }
}


之后我们开始写一个自定义的头部按钮来方便我们想要的布局


- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        UIImage *image = [UIImage imageNamed:@"arrow-right"];
        [self setImage:image forState:UIControlStateNormal];
        self.imageView.contentMode = UIViewContentModeScaleAspectFit;
        //[self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        _open = NO;
    }
    return self;
}

- (void)setOpen:(BOOL)open
{
    _open = open;
    //设定点击旋转动画效果
    [UIView beginAnimations:nil context:nil];
    self.imageView.transform = CGAffineTransformMakeRotation(self.isOpen?M_PI_2:0);
    [UIView commitAnimations];
}


有一个BOOL型的成员_open来记录button是否被点击的状态,在点击时,左侧的图片有一个短暂的旋转动画效果。


然后设置图片以及标题的位置


//图像显示位置
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    return CGRectMake(RMarginX, RMarginY, RIconSide, RIconSide);
}

//标题显示位置
- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    return CGRectMake(RIconSide + 4*RMarginX, 0, contentRect.size.width, contentRect.size.height);
}

在drawRect中还绘制了底部的分割线以及光泽,不过由于背景没有绘制渐变,光泽效果有些突兀,若想具体了解绘制方法的使用,可以参见UIKit和Core Graphics绘图——绘制光泽,仿射变换与矩阵变换


绘制底边


    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGContextSaveGState(context);
    CGContextSetStrokeColorWithColor(context, [UIColor darkGrayColor].CGColor);
    CGContextMoveToPoint(context, 0, rect.size.height);
    CGContextAddLineToPoint(context, 320, rect.size.height);
    CGContextSetLineWidth(context, 2.0f);
    CGContextStrokePath(context);
    CGContextRestoreGState(context);

然后是光泽效果


    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    UIColor *light = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.1];
    UIColor *dark = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.35];
    NSArray *colors = @[(__bridge id)light.CGColor, (__bridge id)dark.CGColor];
    CGFloat locations[] = {0.0, 1.0};
    
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);
    
    CGContextSaveGState(context);
    CGPoint start = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
    CGPoint end = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
    CGContextDrawLinearGradient(context, gradient, start, end, 0);
    
    CGColorSpaceRelease(colorSpace);
    CGGradientRelease(gradient);
    CGContextRestoreGState(context);

接着我们还需要自定义一个单元格类来接受和绘制数据,

具体实现类似于上篇博客中介绍的手工绘制单元格的内容


这里只看数据绑定的部分


- (void)bindFriend:(NSDictionary *)myFriend
{
    _name = myFriend[@"name"];
    _online = [myFriend[@"isonline"] boolValue];
    _headerImage = [UIImage imageNamed:myFriend[@"imagename"]];
    
    [self setNeedsDisplay];
}


在完成头部绘制以及单元格绘制的准备后,我们就可以在控制器中实现代理方法,讲数据排版到界面上了。


显示头部视图


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    HeaderButton *header = _headers[@(section)];
    if (!header)
    {
        header = [HeaderButton buttonWithType:UIButtonTypeCustom];
        header.bounds = CGRectMake(0, 0, 320, RHeaderHeight);
        header.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.8 alpha:1.0];
        header.titleLabel.font = [UIFont systemFontOfSize:16.0f];
        NSString *title = _groupNames[section];
        [header setTitle:title forState:UIControlStateNormal];
        [header addTarget:self action:@selector(expandFriends:) forControlEvents:UIControlEventTouchUpInside];
        [_headers setObject:header forKey:@(section)];
    }
    return header;
}

头部点击的监听方法


- (void)expandFriends:(HeaderButton *)header
{
    header.open = !header.isOpen;
    [self.tableView reloadData];
}

点击的时候改变header的_open值,然后刷新视图内容。


根据header的_open来确定是否显示section中的列表

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    HeaderButton *header = _headers[@(section)];
    NSArray *array = [self arrayWithSection:section];
    NSInteger count = header.isOpen?array.count:0;
    return count;
}


绑定数据并且显示单元格


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    HRFriendsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    NSArray *array = [self arrayWithSection:indexPath.section];
    [cell bindFriend:array[indexPath.row]];
    
    return cell;
}


这样我们的工作几乎就完成了,下面来看一下效果图





具体的demo源码:点击打开链接


以上就是本篇博客全部内容,欢迎指正和交流。转载请注明出处~



文章评论

程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
如何成为一名黑客
如何成为一名黑客
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
程序员和编码员之间的区别
程序员和编码员之间的区别
中美印日四国程序员比较
中美印日四国程序员比较
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
我是如何打败拖延症的
我是如何打败拖延症的
总结2014中国互联网十大段子
总结2014中国互联网十大段子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
老程序员的下场
老程序员的下场
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
那些争议最大的编程观点
那些争议最大的编程观点
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
程序员都该阅读的书
程序员都该阅读的书
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
代码女神横空出世
代码女神横空出世
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
旅行,写作,编程
旅行,写作,编程
程序员应该关注的一些事儿
程序员应该关注的一些事儿
 程序员的样子
程序员的样子
我的丈夫是个程序员
我的丈夫是个程序员
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
10个调试和排错的小建议
10个调试和排错的小建议
程序员必看的十大电影
程序员必看的十大电影
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
编程语言是女人
编程语言是女人
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
每天工作4小时的程序员
每天工作4小时的程序员
为什么程序员都是夜猫子
为什么程序员都是夜猫子
Java程序员必看电影
Java程序员必看电影
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
一个程序员的时间管理
一个程序员的时间管理
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有