fighting~iOS开发-高级汇总iOS基础控件

从零开始UICollectionView(1)--基本实现

2016-10-29  本文已影响517人  BradleyJohnson

UICollectionView简介

NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionView : UIScrollView

打开UICollectionView的.h文件可以发现,UIcollectionView自iOS6以后加入UIKit框架的,它跟UITableView一样继承自UIScrollView。所以在目前市场上所有版本的iPhone上,基本都能支持使用UICollectionView。而且在对数据的展示和UI的构建上,UICollectionView也甩出UITableView十八条街。

UICollectionView的实现说简单挺简单的,无非也就是两个代理和数据源的配合,比UITableView略微复杂的就是有一个需要继承自UICollectionViewLayout的布局信息。
但是说复杂也能很复杂,包括整个UICollectionView的定制布局(瀑布流等)和布局动画以及插入删除item时的动画,也是一个值得深究的控件。

本章主要是简略的实现一个有头视图、尾视图和展示视图的纵向UICollectionView。更为复杂的定制布局我们会在以后的章节详细展开。

1.先说说 Layout

NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionViewLayout : NSObject <NSCoding>

所有关于UICollectionView的精髓,几乎都在这个类上面,它基本确定了整个UICollectionView的布局信息甚至包括一些动画效果,但是定制它是一个问题,而且它是一个抽像类,不能直接被使用,需要定义一个继承自它的子类,然后来徐徐展开。
但是Apple官方给我们已经定制好了一个类 : UICollectionViewFlowLayout ,这个类继承自UICollectionViewLayout,并且定制好了代理方法来方便我们控制UICollectionView的布局,但是也仅仅限制于网格布局。
下面我们就是用UICollectionViewFlowLayout来写我们的简易UICollectionView Demo。

2.代码开撸

2.1 先写基本代码,兵马未动粮草先行,我们先构建一个模拟的数据源数组,再创建一个UICollectionView,关联上UICollectionViewFlowLayout的对象,设置代理,注册好Cell和Header、Footer的信息。
//数据源
-(NSArray *)dataArray
{
    if (!_dataArray) {
        _dataArray = [[NSArray alloc] init];
    
        NSMutableArray * theArray = [NSMutableArray array];
        for (NSInteger index = 0; index < 3; index++) {
            NSMutableArray * subArray = [NSMutableArray array];
            for (NSInteger indexJ = 0; indexJ < 10; indexJ++) {
                MainModel * model = [MainModel new];
                model.indexStr = [NSString stringWithFormat:@"%ld-%ld",index,indexJ];
                [subArray addObject:model];
            }
            [theArray addObject:[NSArray arrayWithArray:subArray]];
        }
    
        _dataArray = [NSArray arrayWithArray:theArray];
    }

    return _dataArray;
}
//UICollectionView视图
-(UICollectionView *)mainCollectionView
{
    if (!_mainCollectionView) {
        UICollectionViewFlowLayout * layout =     [UICollectionViewFlowLayout new];
        layout.scrollDirection = UICollectionViewScrollDirectionVertical;
        layout.sectionHeadersPinToVisibleBounds = NO;//头部视图悬停设为YES
      layout.sectionFootersPinToVisibleBounds = NO;//尾部视图悬停设为YES
    
      _mainCollectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
      _mainCollectionView.backgroundColor = [UIColor whiteColor];
      _mainCollectionView.delegate = self;
      _mainCollectionView.dataSource = self;
    
      [_mainCollectionView registerClass:[MainCollectionViewCell class] forCellWithReuseIdentifier:[MainCollectionViewCell reuseIdentifier]];
      [_mainCollectionView registerClass:[MainCollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[MainCollectionHeaderView reuseIdentifier]];
      [_mainCollectionView registerClass:[MainCollectionFooterView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:[MainCollectionFooterView reuseIdentifier]];
    }

return _mainCollectionView;
 }
2.2 然后我们添加代理,这里我们通过代理的方式控制布局,这样更易于我们的操控。

UICollectionViewDelegate:主要管理于用户交互方面
UICollectionViewDataSource:主要管理视图数据源方面
UICollectionViewDelegateFlowLayout:主要管理布局信息方面

@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
UICollectionView Data Source methods (代理里面还有许多方法,我们主要展示最关键的几个)
//返回多少个组
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView   *)collectionView
{
    return self.dataArray.count;
}
//返回每组多少个视图
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    NSArray * subArray = self.dataArray[section];
    return subArray.count;
}
//返回视图的具体事例,我们的数据关联就是放在这里
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MainCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:[MainCollectionViewCell reuseIdentifier] forIndexPath:indexPath];

    cell.backgroundColor = [UIColor orangeColor];
    cell.contentView.frame = cell.bounds;
    cell.backgroundColor = [UIColor lightGrayColor];

    MainModel * model = self.dataArray[indexPath.section][indexPath.row];

    cell.title = model.indexStr;

    return cell;
}
UICollectionView Delegate method (代理里面还有许多方法,我们主要展示最关键的几个)
//选中某个 item 触发
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"选中 : %ld--%ld",indexPath.section,indexPath.item);
}

//取消某个 item 触发
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"取消选中 : %ld--%ld",indexPath.section,indexPath.item);
}
UICollectionView Delegate FlowLayout method (代理里面还有许多方法,我们主要展示最关键的几个)
// cell 尺寸
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake((self.view.bounds.size.width-5-5-10*2)/3.0, 50);
}

// 装载内容 cell 的内边距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    return UIEdgeInsetsMake(5, 5, 5, 5);
}

//最小行间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
    return 10.0f;
}

//item最小间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
    return 10.0f;
}

//头视图尺寸
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    return CGSizeMake(self.view.bounds.size.width, 50);
}

//尾视图尺寸
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
    return CGSizeMake(self.view.bounds.size.width, 50);
}
2.3 最后是我们的实现效果:
纵向效果

上图是纵向效果,如果需要横向,则改一下UICollectionViewFlowLayoutscrollDirection属性即可,当然啦,尺寸各方面需要再细细调节,简单的很,就需要各位看官慢慢探索了。


3.下节预告,我们将依托UICollectionView来做一个自由移动Cell的关键字选框。效果如下:
自由移动Cell
注:若你觉得这文章确实帮到你了,或是支持一下原创技术文章,请为我点个赞。大爷若是还能打赏打赏,那就更好不过了。
上一篇 下一篇

猜你喜欢

热点阅读