zoukankan      html  css  js  c++  java
  • iOS UI基础-9.0 UITableView基础

    在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView。UITableView继承自UIScrollView,因此支持垂直滚动,而且性能极佳。

    UITableView有两种样式:

    • 一列显示:UITableViewStylePlain
    • 分组显示:UITableViewStyleGrouped

    tableView展示数据的过程

     1.调用数据源的下面方法得知一共有多少组数据

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

     2.调用数据源的下面方法得知每一组有多少行数据

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

     3.调用数据源的下面方法得知每一行显示什么内容

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

    常见的属性

        // 表格行线条的颜色
        self.tableView.separatorColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:0 alpha:255/255.0];
        // 显示表格行线条的样式,UITableViewCellSeparatorStyleNone为没有线条
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        
        // 表格的头部控件(直接显示表格的最顶部),一般用来显示广告
        self.tableView.tableHeaderView = [UIButton buttonWithType:UIButtonTypeContactAdd];
        // 表格的底部控件,一般用来加载更多数据
        self.tableView.tableFooterView = [[UISwitch alloc] init];

        // 行选中为透明

        cell.selectionStyle=UITableViewCellSeparatorStyleNone;

    Cell的重用代码

    UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 1.定义一个cell的标识。static修饰局部变量:可以保证局部变量只分配一次存储空间(只初始化一次)
          static NSString *ID = @"mjcell";
        
        // 2.从缓存池中取出cell
          UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        
        // 3.如果缓存池中没有cell
          if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
         }
        
        // 4.设置cell的属性...
          return cell;
    }

    右边索引条

    已经有相应的数据源,实现即可

    /**
     *  返回右边索引条显示的字符串数据
     */
    - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
    {
        return [self.groups valueForKeyPath:@"title"];
    }

    效果:

    刷新表格

    // 全局刷新(每一行都会重新刷新)
    - (void)reloadData;
    
    // 局部刷新(使用前提: 刷新前后, 模型数据的个数不变)
    - (void)reloadRows:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
    
    // 局部删除(使用前提: 模型数据减少的个数 == indexPaths的长度)
    - (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

    实例:

        // 全部刷新
         [self.tableView reloadData];
        
        // 局部刷新,row指的是第几行,inSection指的是第几组
        NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:0];
        [self.tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationBottom];

    滑动删除与新增

      

    只需要实现tableview代理即可

    /**
     *  当tableView进入编辑状态的时候会调用,询问每一行进行怎样的操作(添加删除)
     */
    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return UITableViewCellEditingStyleDelete;
        //return indexPath.row %2 ? UITableViewCellEditingStyleDelete : UITableViewCellEditingStyleInsert;
    }

    如果显示的是英文Delete,可以通过设置模拟器的语言,同时增加中文语言

    选中InfoPlist.strings和InfoPlist.strings

    监听点击滑动删除按钮

    /**
     *  如果实现了这个方法,就自动实现了滑动删除的功能
     *  点击了删除按钮就会调用
     *  提交了一个编辑操作就会调用(操作:删除添加)
     *  @param editingStyle 编辑的行为
     *  @param indexPath    操作的行号
     */
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (editingStyle == UITableViewCellEditingStyleDelete) { // 提交的是删除操作
            // 1.删除模型数据
            [self.contacts removeObjectAtIndex:indexPath.row];
            
            // 2.刷新表格
            // 局部刷新某些行(使用前提:模型数据的行数不变)
            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
            
            // 3.归档
            [NSKeyedArchiver archiveRootObject:self.contacts toFile:MJContactsFilepath];
        } else if (editingStyle == UITableViewCellEditingStyleInsert) {
            // 1.修改模型数据
            MJContact *contact = [[MJContact alloc] init];
            contact.name = @"jack";
            contact.phone = @"10086";
            [self.contacts insertObject:contact atIndex:indexPath.row + 1];
            
            // 2.刷新表格,使用局部刷新
            NSIndexPath *nextPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0];
            [self.tableView insertRowsAtIndexPaths:@[nextPath] withRowAnimation:UITableViewRowAnimationBottom];
    //        [self.tableView reloadData];
        }
    }

    其它属性

        // 2.设置每一组头部尾部的高度
        self.tableView.sectionFooterHeight = 0;
        self.tableView.sectionHeaderHeight = 10;
        
        // 3.设置背景色
        self.tableView.backgroundView = nil;
        self.tableView.backgroundColor = IWGlobalBgColor;

     常用实例:

    #pragma mark - 初始化界面
    
    - (void)setupTableView
    {
        _tableView= [[UITableView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight) style:UITableViewStyleGrouped];;
        _tableView.dataSource = self;
        _tableView.delegate=self;
        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        _tableView.tableHeaderView = [self tableHeaderView];
        _tableView.tableFooterView = [UIView new];
        [self.view addSubview:_tableView];
    }
    
    // 初始化头部
    - (UIView *)tableHeaderView
    {
        
    }
    
    #pragma mark - UITableViewDataSource数据源方法
    // 返回分组数
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        NSLog(@"计算分组数");
        return 1;
    }
    
    // 返回每组行数
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        NSLog(@"计算每组(组%i)行数",section);
        return group1.contacts.count;
    }
    
    // 返回每行的单元格
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        static NSString *ID = @"RFMeTableViewCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
        }
        cell.textLabel.text = @"文字";
        cell.imageView.image = [UIImage imageNamed:@"me_phone_icon"];
        return cell;
    }
    
    // 返回每组头标题名称
    -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
        NSLog(@"生成组(组%i)名称",section);
        return group.name;
    }
    
    // 返回每组尾部说明
    -(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{
        NSLog(@"生成尾部(组%i)详情",section);
        return group.detail;
    }
    
    #pragma mark - UITableViewDelegate 代理方法
    // 设置分组标题内容高度
    -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
        if(section==0){
            return 50;
        }
        return 40;
    }
    
    // 设置每行高度(每行高度可以不一样)
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        return 45;
    }
    
    // 设置尾部说明内容高度
    -(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
        return 40;
    }
    
    // 点击行
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
        
    }

     点击效果

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
    {
        //当手指离开某行时,就让某行的选中状态消失
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
    }

     TableView样式

    如果带有图标,我们使用系统自带的tableviewCell.ImageView.image来设置的话,会发现,底下的这条线没有包括图标,类型QQ的效果,如:

    现在有一个需求,是改成类型微信的显示效果,底部是线包括图标,如:

     

    我们会发现,当tableviewcell.imageView.image 为空的时候,横线是到图标的这个位置的。因而,简单的做法是,不使用系统的,自定义一个imageview,并设置tableviewcell.textLabel的X值。

        // 1.设置基本数据
        if (item.icon) {
            _iconImage.image = [UIImage imageNamed:item.icon];
        } else {
            _iconImage.frame = CGRectZero;
        }
        //self.imageView.image = [UIImage imageNamed:item.icon];
        self.textLabel.text = item.title;
        self.detailTextLabel.text = item.subtitle;

    改为textLable的X值

    - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        // 调整子标题的x
        self.detailTextLabel.x = CGRectGetMaxX(self.textLabel.frame) + 5;
        
        if (_item.icon) {
            self.textLabel.x = 40;
        }
    }

    参考完成代码:

    //
    //  MeCommonCell.m
    //  99SVR
    //
    //  Created by jiangys on 16/6/2.
    //  Copyright © 2016年 xia zhonglin . All rights reserved.
    //
    
    #import "MeCommonCell.h"
    #import "CommonCellLabelItem.h"
    #import "CommonCellArrowItem.h"
    
    @interface MeCommonCell()
    /** 箭头 */
    @property (nonatomic, strong) UIImageView *rightArrow;
    /** 标签 */
    @property (nonatomic, strong) UILabel *rightLabel;
    /** 图标 这里不使用自带的self.imageView.image,因为底部横线不会包括自带的图标*/
    @property(nonatomic, strong) UIImageView *iconImage;
    @end
    
    @implementation MeCommonCell
    
    #pragma mark - 懒加载右边的view
    - (UIImageView *)rightArrow
    {
        if (_rightArrow == nil) {
            UIImageView *arrowImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrow"]];
            arrowImageView.size = (CGSize){13,13};
            self.rightArrow = arrowImageView;
        }
        return _rightArrow;
    }
    
    - (UILabel *)rightLabel
    {
        if (_rightLabel == nil) {
            self.rightLabel = [[UILabel alloc] init];
            self.rightLabel.textColor = COLOR_Text_Gay;
            self.rightLabel.font = Font_14;
        }
        return _rightLabel;
    }
    
    #pragma mark - 初始化
    + (instancetype)cellWithTableView:(UITableView *)tableView
    {
        static NSString *ID = @"MeCommonCell";
        MeCommonCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        if (cell == nil) {
            cell = [[MeCommonCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:ID];
        }
        return cell;
    }
    
    - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
            _iconImage = [[UIImageView alloc] initWithFrame:CGRectMake(15,0, 17, self.height)];
            _iconImage.contentMode = UIViewContentModeScaleAspectFit;
            [self.contentView addSubview:_iconImage];
            
            // 设置标题的字体
            self.textLabel.font = Font_15;
            self.textLabel.textColor = COLOR_Text_Black;
            self.detailTextLabel.font = Font_14;
            
            // 设置cell的默认背景色
            self.backgroundColor = [UIColor whiteColor];
        }
        return self;
    }
    
    #pragma mark - 调整子控件的位置
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        // 调整子标题的x
        self.detailTextLabel.x = CGRectGetMaxX(self.textLabel.frame) + 5;
        
        if (_item.icon) {
            self.textLabel.x = 40;
        }
    }
    
    - (void)setItem:(CommonCellItem *)item
    {
        _item = item;
        
        // 1.设置基本数据
        if (item.icon) {
            _iconImage.image = [UIImage imageNamed:item.icon];
        } else {
            _iconImage.frame = CGRectZero;
        }
        //self.imageView.image = [UIImage imageNamed:item.icon];
        self.textLabel.text = item.title;
        self.detailTextLabel.text = item.subtitle;
        
        // 2.设置右边的内容
        if ([item isKindOfClass:[CommonCellArrowItem class]]) {
            self.accessoryView = self.rightArrow;
        } else if ([item isKindOfClass:[CommonCellLabelItem class]]) {
            CommonCellLabelItem *labelItem = (CommonCellLabelItem *)item;
            // 设置文字
            self.rightLabel.text = labelItem.text;
            // 根据文字计算尺寸
            self.rightLabel.size = [labelItem.text sizeMakeWithFont:self.rightLabel.font];
            self.accessoryView = self.rightLabel;
        } else { // 取消右边的内容
            self.accessoryView = nil;
        }
    }
    @end
    View Code

     网摘一些小总结:

    //这句话不显示多余的单元格
        self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
    
    // 这句话不显示单元格之间的分割线
        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    
    
    // 这句话在单元格的最后显示一个箭头
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    
    
    //--- 点击cell的时候 cell不会产生高亮状态 ---
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    
    // --- 写在viewdidload里面cell自适应高度 ----
    tableView.rowHeight = UITableViewAutomaticDimension; // 自适应单元格高度
     tableView.estimatedRowHeight = 50; //先估计一个高度
    
    // 去掉UItableview headerview黏性(sticky)
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
    CGFloat sectionHeaderHeight = 40;
        if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
            scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
        }
        else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
            scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
        }
    }
    
    // 获取手势点击的是哪一个cell的坐标
    NSIndexPath *indexPath = [self.tableView indexPathForCell:((UITableViewCell *)longPress.view)];
    
    // 局部刷新
    //一个section刷新    
    NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:2];    
    [tableview reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];    
    
    //一个cell刷新   
    NSIndexPath *indexPath=[NSIndexPath indexPathForRow:3 inSection:0];   
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone]; 
    
    // 关于UITableView如何跳转到最后一行或者任意指定行。
    其实现如下:
    [self.chatTableView scrollToRowAtIndexPath:
    [NSIndexPath indexPathForRow:[self.chatArray count]-1 inSection:0]
      atScrollPosition: UITableViewScrollPositionBottom
      animated:NO];
    
    // 点击button时获取button所在的cell的indexpath
        UIButton *button = sender;
        HeroDermaTableViewCell *cell = (HeroDermaTableViewCell *)[[button superview] superview];
        NSIndexPath *indexPath = [_tableView indexPathForCell:cell];

    分组状态下,顶部留白,解决办法

    table.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, CGFLOAT_MIN)]; 

  • 相关阅读:
    Java Web 开发必须掌握的三个技术:Token、Cookie、Session
    $.proxy和$.extend
    手机端和网页端使用同一后台时进行会话控制
    js中使用EL表达式总结
    Durandal入门
    RequireJs入门
    阿里云Prismplayer-Web播放器的使用
    Mac系统实现git命令自动补全
    Mac系统的终端显示git当前分支
    Gulp实现css、js、图片的压缩以及css、js文件的MD5命名
  • 原文地址:https://www.cnblogs.com/jys509/p/4813394.html
Copyright © 2011-2022 走看看