你真的会用UITableView嘛

作者: StrongX | 来源:发表于2016-03-24 22:17 被阅读3100次

    UITableView是工程开发中最经常使用到的UI控件,但是你真的了解它嘛,这里记录几点有用的但你可能并不知道的。

    • 当我们的数据未能显示满一屏幕的时候,UITableView会显示多余的横线,这个时候你如果希望去掉这些横线,你可以加上这句话。
        self.tableView.tableFooterView = [[UIView alloc]init];
    
    • UITableView的分割线默认是开头空15像素点的(好像是15来着~~),产品经理有时候希望能够定格显示,那么你可能会这么做。
            self.tableView.separatorInset = UIEdgeInsetsZero;
    

    但是你很快就会发现这么做并没有效果,这是因为<code>separatorInset</code>这个属性在iOS7以后就已经失效了,但是我们还是能够达到同样的效果,你可以在你的tablevView的代理协议实现界面加上下面这段代码:

    /**
     *  分割线顶头
     */
    -(void)viewDidLayoutSubviews
    {
        if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
            [self.tableView setSeparatorInset:UIEdgeInsetsMake(0,0,0,0)];
        }
        
        if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
            [self.tableView setLayoutMargins:UIEdgeInsetsMake(0,0,0,0)];
        }
    }
    -(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
            [cell setSeparatorInset:UIEdgeInsetsZero];
        }
        if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
            [cell setLayoutMargins:UIEdgeInsetsZero];
        }
    }
    

    再次运行,好了我们的UITableView终于顶头显示分割线了。

    • 很多情况下我们的UITableViewCell的高度是动态不确定的,比如说很多聊天的界面都需要我们去动态的计算cell的高度,你可能会在<code>heightForRowAtIndexPath</code>代理协议方法中返回你计算好的cell高度,然后在苹果推出约束以后,我们其实有更加方便的方法去实现相同的效果。你可以尝试在你的代码中加入以下两行代码:
     self.tableView.estimatedRowHeight = 68.0;
     self.tableView.rowHeight = UITableViewAutomaticDimension;
    

    再次运行你的程序,其实你发现了好像你的cell并没有动态的返回高度,这是因为上面说了,这两行代码必须配合约束来使用。
    我们拖出一个SB,然后在cell上放上一个label,讲label的<code>numberOfLines</code>属性设置为0,然后设置好label的上下左右约束,然后再对label的内容进行赋值,再次运行你的程序,这个时候你的cell就会动态的显示高度了,label的高度取决于你的内容的多少,同时按照你的约束进行显示。
    -你可能写过这样下面这样的代码

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
        [tableView deselectRowAtIndexPath:indexPath animated:true];
        [tableView beginUpdates];
        ROW--;//此操作表示减少数据源的个数。
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
        [tableView endUpdates];
    }
    

    用一个动画来删除某一个cell,其中有两行代码特别有意思:

        [tableView beginUpdates];
        [tableView endUpdates];
    

    这俩吧其实和<code>[tableView reloadData]</code>作用类似,但是这俩货却能非常轻松的创造出不错的效果,比如说和我们上一点说的用约束来控制label的行高相结合的是的时候,我们先来看一下效果:

    一个tableView点击缩放的效果

    其实我的代码很少,核心代码只有以下几行:

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
        [tableView deselectRowAtIndexPath:indexPath animated:true];
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        UILabel *label = [cell.contentView viewWithTag:1000];
        [tableView beginUpdates];
        if (label.numberOfLines == 0) {
            label.numberOfLines = 1;
        }else{
            label.numberOfLines = 0;
        }
        [tableView endUpdates];
    }
    

    我用SB创建了一个UITableView,然后在cell上放置了一个label,初始化label 的<code>numberOfLines</code>然后在界面上设置tableView

    self.tableView.estimatedRowHeight = 68.0;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    

    然后在他的点击动作中改变label的<code>numberOfLines</code>,同时结合使用:

    [tableView beginUpdates];
     [tableView endUpdates];
    

    像上面po出来的代码那样,这个时候你如果使用[tableView reloadData]也能够达到改变cell高度的效果,但是界面上就不会有使用[tableView beginUpdates]那么流畅,以此类推,其实在很多地方都可以用<code>[tableView beginUpdates]</code>来代替<code>[tableView reloadData]</code>来达到更好的效果.

    • 你可能会经常忽略UITableView的一些属性和回调,必须下面这个方法:
    -(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
        CGFloat offSet = tableView.contentOffset.y;
        if (offSet<=0) {
            return;
        }
        CGRect oldRect = cell.frame;
        CGRect newRect = cell.frame;
        newRect.origin.x += 50;
        cell.frame = newRect;
        [UIView animateWithDuration:0.5 animations:^{
            cell.frame = oldRect;
        }];
    }
    

    如果你这么写会简单的有一个展示的动画,这个回调就是在cell展示到屏幕的时候发起的动作。
    还有这个属性:<code>tableView.visibleCells</code>,你的产品经理可能会要求你的cell在滚动的时候进行一些展示类的动画----滚动的时候进行展开收起之类的,这样的话你可以这么做:

    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
        for (UITableViewCell *cell in _tableView.visibleCells) {
            /**
             *  你可以在这里对当前的cell进行一些操作
             *
             */
        }
    }
    

    这个属性会返回即将展示到屏幕上的cell,而放在这个滚动的回掉中你就可以对你的cell进行不停的调整了,具体能做出什么动画,就靠你的想象能力了。

    • tableView可能会造成你的Controller过于庞大,或许你可以使用MVVM类似的构架来瘦身你的Controller。。。。。。
      更多好文:http://www.strongx.cn

    相关文章

      网友评论

      • 神奇水滴:感謝 最近從android轉swift, 在樓主這邊找到了很多實用的文章
      • e44c4f6fe069:你好,我想请问一下,cell中怎么获取数组中的值,我已经将数据库中的值存入了数组中,不知道在cell中怎么显示出来
        kinmo:@_try 数组[indexpath.row]
        e44c4f6fe069:@_try @_ 就是想问怎么传
        StrongX:传过去
      • 3b73ac1e6515:博客打不开了???
        StrongX:挂了。换了个sbookreview.com
      • 四月_明朗:建议:在不同iOS系统的API是不同得,此中方法,建议楼主标记一下。否则会有坑
      • L了个Y:大哥,点击变高那个宠用问题怎么解决
        L了个Y:@文刀洋 额,重用起来高度全乱了
      • WKCaesar:我认错,刚才看岔了,以为把分割线重绘了……:joy:
      • WKCaesar:分割线顶头的那个,没有特殊的要求的话没必要那么写。viewcontroller里面有个方法是layout什么的在那个里面设置tableview的两个属性layout什么的=uiedgisetzero,还有一个就是你上面写的那个。 然后在tableview代理的willdisplaycell里面设置cell的layout什么的那个属性也为uiedginsetzero就可以让分割线的宽度等于tableview的宽度。上面说的那个属性是真的记不住……
      • 我是Python小白:very nice~ 解决了我的燃眉之急. :joy:
      • bd47d2f54ece:印象笔记好系统短信的拉伸效果是不是就是这个方法
      • 2088e94db1b4:发现cell不用注册也可以,问一下注册和不注册有什么不同,或者说潜在问题吗?
      • 超_iOS:[TableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationBottom];
        请教楼主这个方法的实现原理是怎样的,因为只有一个cell时会崩溃,但是用reloaddata就没啥事.问题详情链接求解答http://www.jianshu.com/p/2229b3616552
        StrongX:@小菜超 deleteSections 你得配合update使用
        超_iOS:@小菜超 删除了大神
        StrongX:@小菜超 大体的报错原因应该是删除cell前和删除cell后返回cell的个数需要相等,你必须从你的dataSource(也就是你存储cell内容 同时也是返回cell个数的那个数组)中删除你删除的这条元数据。
      • a05832db24ea:楼主对NSTableView熟吗,有个问题请教
        a05832db24ea: @StrongX 没事,问题已经解决了
        StrongX:@屎壳郎123 不熟
      • 闲得一B:有用
      • b59457960ac9:我觉得分割线顶头,用UIview画一条也挺方便的…据我了解配合约束的设置行高好像只支持ios8以上系统
      • 随意_M: :relaxed: 今天刚好要用到这个 :v: 拿走不谢
      • 方振:学习了
      • 雾帆岛:总结得不错 自适应高度只有label计算方法 咋不把其他的都总结进去
        喵小帅:@雾帆岛 哪里特殊?因为有lines么?
        雾帆岛:@StrongX label例子有点特殊
        StrongX:@雾帆岛 举一反三,就不重复累赘了。
      • OCSwift:实用
      • Keep丶Dream:点击缩放对于自定义的cell有用么
        StrongX:@一袭白衣 要用约束
      • huangman:一直以为UITableView不能支持autolayout,也找了好久终于看到了。以后就省事了不用去每个cell计算高度了!
      • coderWen:谢谢楼主分享干货, :relieved: 一个tableView点击缩放的效果有源码参考理解吗...
        StrongX:@coderWen 不给源码的意思就是希望你能够自己去尝试下,跟着文中的描述 应该是很简单的
      • 垚子:mark

      本文标题:你真的会用UITableView嘛

      本文链接:https://www.haomeiwen.com/subject/ieprlttx.html