美文网首页学习一下UIiOS
D14:UICollectionView(单分组, 多分组, 模

D14:UICollectionView(单分组, 多分组, 模

作者: Vinc | 来源:发表于2015-05-22 08:46 被阅读7183次

    UICollectionView网格视图

    网格视图是能够显示多列的列表视图, 弥补了UITableView不方便实现多列的缺点, 在iOS6之后才有这个控件
    Inheritance
    NSObject
    UIResponder
    UIView
    UIScrollView
    UICollectionView

    UICollectionViewFlowLayout: 确定网格视图的布局

    上下左右的间距: sectionInset(left, top, bottom, right)
    每一个Cell的大小: itemSize(width, height)
    横向Cell之间的间距: minimumInteritemSpacing
    纵向Cell之间的间距: minimumLineSpacing


    目录

    一.单分组的网格视图

    1. 系统的Cell
    2. 代码自定制的Cell
    3. xib自定义Cell

    二.多分组的网格视图

    1. Header
    2. Footer

    三.实现穷游App的折扣界面

    1. 创建模型类, 导入MyDownloader类(用于从网上下载数据)
    2. 解析下载到的JSON数据, 创建数据源(此处下载到的是JSON数据, 以后也可能需要下载解析XML数据)
    3. 自定义Cell
    4. 常规流程: 创建CollectionView, 遵守协议实现方法

    一.单分组的网格视图

    1. 使用系统的Cell
      1. 创建数据源

      2. 创建UICollectionView对象

        1. 指定初始化方法

           // 第一个参数: 位置    
           // 第二个参数: 布局对象
           - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;  
           UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 20, kWidthOfScreen, kHeightOfScreen - 20) collectionViewLayout:layout];  
          
        2. 布局对象 UICollectionViewLayout

          // 布局对象是一个UICollectionViewLayout类型的对象
          // 由于我们是规则的布局, 可以直接使用UICollectionViewFlowLayout对象
          // UICollectionViewFlowLayout继承于UICollectionViewLayout
          UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
          // 1. 上下左右的间距
          /*
           UIEdgeInsets:<#CGFloat top#>(上面的间距), <#CGFloat left#>(左边), <#CGFloat bottom#>(底部), <#CGFloat right#>(右边)
           */
          layout.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5);
          // 2. cell的大小
          layout.itemSize = CGSizeMake(180, 100);
          // 3. 横向间距
          layout.minimumInteritemSpacing = 5;
          // 4. 纵向间距
          layout.minimumLineSpacing = 10;
          
        3. 设置UICollectionView对象的属性

           // 设置代理
           collectionView.delegate = self;
           // 设置数据源代理
           collectionView.dataSource = self;
           // 设置白色背景
           collectionView.backgroundColor = [UIColor whiteColor];
           
           // 注册cell的类型
           // 以代码的方式注册Cell的类型, 表示创建Cell的时候用这个类型来创建
           /*
            第一个参数: Cell的类型
            第二个参数: 重用标志
            */
           [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kCellReuseId];
           
           // 添加到父视图上
           [self.view addSubview:collectionView];  
          
      3. 遵守协议, 实现协议方法
        - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

         // 返回每一个Cell的对象
         // UICollectionView上面的每一个Cell是UICollectionViewCell类型(或子类型)的对象
         // UICollectionViewCell也是一个视图
         - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
         {
             // 从重用队列里面获取
             /*
              第一个参数: 重用id
              第二个参数: cell的位置
              */
             
             // UITableView      -> NSIndexPath:section row
             // UICollectionView -> NSIndexPath:section item
             UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellReuseId forIndexPath:indexPath];
         
             // 不需要再创建, 从dequeueReusableCellWithReuseIdentifier方法李米娜一定能够获取到
             // 设置背景颜色
             cell.backgroundColor = [UIColor grayColor];
             
             // 显示文字
             UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 30, 180, 40)];
             label.textAlignment = NSTextAlignmentCenter;
             // 获取文字
             NSString *str = self.dataArray[indexPath.item];
             label.text = str;
             // 添加到父视图
             [cell.contentView addSubview:label];
             
             return cell;
         }  
        
      4. 因为每次都是新添一个UILabel, 所以会有滑动出现重影的问题(其实是UILabel的重叠)

         // 解决方法, 在为cell设新的UILabel前移除之前的子视图
            for (UIView *sub in cell.contentView.subviews) {
                [sub removeFromSuperview];
            }
        
    2. 代码自定制的Cell
      1. 创建数据源
      2. 创建UICollectionView对象
        1. 指定初始化方法
          - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
        2. 布局对象 UICollectionViewLayout
        3. 设置UICollectionView对象的属性
      3. 遵守协议, 实现协议方法
      4. 因为自建的cell的控件是其属性, 所以每次重新设置cell的控件的属性不会发生重影的问题
    3. Xib定制的Cell
      1. 创建数据源

      2. 创建UICollectionView对象

        1. 指定初始化方法
          - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;

        2. 布局对象 UICollectionViewLayout (可以使用UICollectionViewDelegateFlowLayout代理来设置)

          Getting the Size of Items
          – collectionView:layout:sizeForItemAtIndexPath:
          Getting the Section Spacing
          – collectionView:layout:insetForSectionAtIndex:
          – collectionView:layout:minimumLineSpacingForSectionAtIndex:
          – collectionView:layout:minimumInteritemSpacingForSectionAtIndex:
          Getting the Header and Footer Sizes
          – collectionView:layout:referenceSizeForHeaderInSection:
          – collectionView:layout:referenceSizeForFooterInSection:
          
        3. 设置UICollectionView对象的属性

        4. 注册cell的类型

           // 注册cell(xib)
           // 第一个参数: xib的对象(UINib类型)
           // 第二个参数: 重用标志
           UINib *nib = [UINib nibWithNibName:@"DataCell" bundle:nil];
           [collectionView registerNib:nib forCellWithReuseIdentifier:kCellReuseId];
          
      3. 遵守协议, 实现协议方法
        - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
        {
        // 从重用列表中获取
        DataCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellReuseId forIndexPath:indexPath];
        ..........................................................................
        }

    代码自定制的cell和xib的区别:注册Cell方法的不同
    - (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier
    - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier


    二.多分组的网格视图

    1. Header
      1. 新建headerView类, 继承自UICollectionReusableView

      2. 注册header

         /*
          第一个参数:header视图对象的类型
          第二个参数:区分是header还是后面的footer
          // UICollectionElementKindSectionHeader表示header类型
          第三个参数:重用标志
          */
         [_collectionView registerClass:[HeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:KHeaderReuseId];
        
      3. 在布局对象的代理协议方法中设置header的大小
        - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
        {
        return CGSizeMake(375, 40);
        }

      4. 返回header对象 UICollectionViewDataSource的协议方法(也可以用来返回footer对象)
        - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
        {
        if (kind == UICollectionElementKindSectionHeader) {
        // header类型

                 // 从重用队列里面获取
                 HeaderView *header = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:KHeaderReuseId forIndexPath:indexPath];
                 
                 // 设置背景颜色
                 header.backgroundColor = [UIColor redColor];
                 // 显示数据
                 header.titleLabel.text = [NSString stringWithFormat:@"第%c组", (int)(indexPath.section + 'A')];
                 return header;
         
             } else if (kind == UICollectionElementKindSectionFooter) {
                 // footer
                 
                 // 从重用队列里面获取
                 FooterView *footer = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:KFooterReuseId forIndexPath:indexPath];
                 
                 footer.backgroundColor = [UIColor purpleColor];
                 // 显示数据
                 footer.titleLabel.text = [NSString stringWithFormat:@"第%c组结束", (int)(indexPath.section + 'A')];
                 return footer;
             }
             return nil;
         }  
        
    2. Footer
      1. 新建FooterView类, 继承自UICollectionReusableView

      2. 注册footer

         [_collectionView registerClass:[FooterView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:KFooterReuseId];
        
      3. 在布局对象的代理协议方法中设置footer的大小
        - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
        {
        return CGSizeMake(375, 40);
        }

      4. 返回footer对象 UICollectionViewDataSource的协议方法(也可以用来返回header对象)


    三.实现穷游App的折扣界面

    1. 创建模型类, 导入MyDownloader类(用于从网上下载数据)
       // 下载数据
       - (void)downloadData
       {
           // 创建myDownloader对象
           MyDownloader *downloader = [[MyDownloader alloc] init];
           // 设置代理
           downloader.delegate = self;
           // 下载数据
           [downloader downloadWithUrlString:kUrl];
       }
       
       // MyDownloader代理方法
       // 下载失败
       - (void)downloaderFail:(NSError *)error downloader:(MyDownloader *)downloader
       {
           NSLog(@"%@", error);
       }
      
    2. 解析下载到的JSON数据, 创建数据源(此处下载到的是JSON数据, 以后也可能下载XML数据)
       // 下载成功
       - (void)downloaderFinish:(MyDownloader *)downloader
       {
           // 下载回来的数据在downloader.receiveData这个属性里
           // JSON解析
           id result = [NSJSONSerialization JSONObjectWithData:downloader.receiveData options:NSJSONReadingMutableContainers error:nil];
           if ([result isKindOfClass:[NSDictionary class]]) {
               // 如果是字典 按照字典来操作
               NSDictionary *dict = result;
               NSArray *array = dict[@"data"];
               for (NSDictionary *dataDict in array) {
                   // NSLog(@"%@", dataDict);
                   
                   // 创建模型对象
                   DataModel *model = [[DataModel alloc] init];
                   [model setValuesForKeysWithDictionary:dataDict];
                   
                   // 添加到数组中
                   [self.dataArray addObject:model];
               }
               // 刷新网格视图
               [_collectionView reloadData];
           }
       }
      
      • 因为上方使用KVC方法来创建模型对象, 所以我们要在模型类的.m文件中重写方法
        - (void)setValue:(id)value forUndefinedKey:(NSString *)key
        {
        }
    3. 自定义Cell
      • DataCell.m
        - (void)config:(DataModel *)model
        {
        // 图片
        [self.picImageView sd_setImageWithURL:[NSURL URLWithString:model.pic]];

              // 价格
              self.priceLabel.text = model.buy_price;
              
              // 名字
              self.nameLabel.text = model.title;
              self.nameLabel.numberOfLines = 2;
              self.nameLabel.font = [UIFont boldSystemFontOfSize:18];
              
              // 时间
              self.timeLabel.text = model.end_date;
              
              // 折扣
              self.discountLabel.text = model.lastminute_des;
          }
        
        • 因为我们的图片是从根据一个网址的字符串去网上下载的,所以我们导入了另一个第三方库UIImageView+WebCache 用于下载网上图片
          - (void)sd_setImageWithURL:(NSURL *)url
          {
          [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
          }
    4. 常规流程: 创建CollectionView, 遵守协议实现方法

    相关文章

      网友评论

      本文标题:D14:UICollectionView(单分组, 多分组, 模

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