iOS UICollectionView 注册步骤、使用方法以及 各种问题 和坑点

写在前面:

调用UICollectionView 步骤:

* 1.添加协议 <UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>注意不要写成UICollectionViewDelegate

*2.初始化UICollectionViewFlowLayout布局 ,并设置布局属性和样式:

UICollectionViewFlowLayout * collectionViewLayout  = [[UICollectionViewFlowLayout alloc]init];

   collectionViewLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;///横向

    collectionViewLayout.minimumInteritemSpacing = 0;//间隙为0

    collectionViewLayout.minimumLineSpacing = 0;//分隔线宽度为0

*3.初始化UICollectionView, 并设置代理 和样式特性:

collectionView  = [[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:imageCollectionViewLayout];

    collectionView.dataSource = self;

    collectionView.delegate = self;

    collectionView.pagingEnabled = YES;//分页效果

    collectionView.bounces = NO;

    collectionView.alwaysBounceHorizontal = YES;

   collectionView.alwaysBounceVertical = NO;

   collectionView.showsHorizontalScrollIndicator = NO;

   collectionView.showsVerticalScrollIndicator = NO;

*4.注册单元格,(也可以在单元格设置里面注册)

[ collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellId];

   // [ collectionView reloadData];//每次进入可能会有 新数据刷入 ,刷新数据  (根据情况设置)

  //  [ collectionView layoutIfNeeded];//每次进入可能会有 新数据刷入 ,刷新界面根据情况设置)

5.设置开启的指定cell 设置 跳转的个数

    [collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:  (*item的下标*)  inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];

6.加入界面

[self.view addSubview:_imageCollectionView];    

7.完成协议和代理

7.1 item  单元格个数

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{}

7.2返回单元格的大小

#pragma mark ---- UICollectionViewDelegateFlowLayout

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{}

7.3 单元格内容

- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {}

 

参考链接:

https://blog.csdn.net/KongMuLianHua/article/details/89338087

https://blog.csdn.net/u013983033/article/details/83095126

一.不调用问题:

不调用- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath方法;

或者

不调用- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath等方法;

原因:

1.协议名称写错:UICollectionViewDelegateFlowLayout --写错成:UICollectionViewDelegate

2.layout写错:UICollectionViewFlowLayout --写错成:UICollectionViewLayout

3.没有设置协议:  ********.delegate = self;

(一般写完上面这三个,在写- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath 时,xcode会自动有代码填充提示,如果没有的话检查一下上面的步骤)

4.   返回单元格的数量为0 ,即*******.count为0,

5.  没有注册你的cell 参考上面的注册

6. 在controller里面写上self.automaticallyAdjustsScrollViewInsets = NO; (未验证)

7.在创建layout 的时候 把layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 注释掉(有人验证过,不过如果是横向滑动就会有问题)

8.可能因为在collection要刷新界面的时候又刷新了其他的界面或者组件

可以设置:

[self.collectionView reloadData];
[self layoutIfNeeded];

 

参考链接:

https://www.jianshu.com/p/3307f5a4d3e3

https://www.jianshu.com/p/cfde1b0c7144

二.cell / item 间隙问题:

代码里没有设置间距,运行效果却有间距,是因为UICollectionView有默认间距,解决办法:

   collectionViewLayout.minimumInteritemSpacing = 0;//间隙为0

    collectionViewLayout.minimumLineSpacing = 0;//分隔线宽度为0

其他原因:

1、iPhone中屏幕的 逻辑像素(pt)和 物理像素(px)的对应关系,

iPhone 3G : 1pt=1px

iPhone4 ~iPhone6s:1pt= 2px

iPhone6s plus(包含)之后:1pt= 3px (1px = 0.3333333...pt)

(注:在iPhone6s plus(包含)之后都是一个pt对应3个px,iPhone4 ~iPhone6s都是一个pt对应2个px,从 [[UIScreen mainScrenn] scale] 可以得出对应比例。)

Tips:

  • 在 xib 或者 storyboard 中使用的都是** pt **而不是px
  • iOS 中的 pt 和安卓中的单位 dp 本质上是一个概念,都是独立像素的意思,只是叫法不一样而已

 

2、举例说明:

 当在iPhone8中 UICollectionView 显示4个等宽的item时,item的 width 为 375.0/4 = 93.75 pt(375pt为iPhone8 独立像素宽度, 1个pt由3个px来渲染) 每个93.75pt的item都有小数: 0.75 pt,而这个0.75pt 无法用3个物理像素点渲染:

 1pt = 3px,所以每个px 只能渲染逻辑长度的0.33 , 2个px 渲染逻辑长度的0.66即0.66pt, 那么剩下的 0.09pt会占用1个px的物理像素去渲染吗,不会!当小于1px时,像素是不可再拆分的,因此产生了临近 1px的空白间隙。有人会问了,它不渲染,第二个item应该由这个px开始才对呀?不是这样的,因为每个item的pt点是固定的,如果一个pt (3个px)里面有一个px物理像素被其他item占用了,这个item 就不会去使用这个pt点了。

要想解决这个问题,有很多方法:

比如

*item取整数 法,避免浮点型数的出现;  

*重写UICollectionViewFlowLayout,还有设置sectionInset;

*设置偏移 item 适当重叠等。

由于手机型号不同,有的手机1pt= 2px,有的1pt= 3px,所以这里推荐取整数法,除非对每个item宽度有极致的要求,否则,人眼很难观察到item的不同;

参考链接

 https://www.jianshu.com/p/87ee1c029fe8

https://blog.csdn.net/ayuapp/article/details/80360745

https://www.jianshu.com/p/4db0be2f4803

三.跳转到指定cell/item 问题

//1.设置内距方法

    //    CGFloat offsetX =  _imageCollectionView.frame.size.width * _imageIndex;

    //    [_imageCollectionView setContentOffset:CGPointMake(offsetX, 0)];

 //2.设置 跳转的个数

        [_imageCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem: 下标数 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];//如设置为yes ,跳转时会有跳转效果

两种方法都可以实现跳转,但是都是先跳转到下标为0的界面,然后跳转到指定的界面,如果刷新不及时,很可能会造成下标为0界面的残留,所以建议,如果是首次进入,可以在-(UICollectionViewCell *)collectionView:( UICollectionView *)collectionView cellForItemAtIndexPath:( NSIndexPath *)indexPath {}中设置其数据为对应的下标的数据,即第0个item第一次进入加载的数据不是第0个数据,而是你传入的数据,之后设置其为对应的数据,很简单,在- (void)viewDidLoad {}中设置一个NSInteger 数就行了。

@interface 你的ViewController () {

        NSInteger * _firstIn;

}

- (void)viewDidLoad {

_firstIn = 0 }

-(UICollectionViewCell *)collectionView:( UICollectionView *)collectionView cellForItemAtIndexPath:( NSIndexPath *)indexPath {

if (_firstIn == 0 ) {

      //你的操作

        _firstIn = 1;

    }

}

参考链接:https://blog.csdn.net/ljw2017/article/details/83088426

四.indexPath.item 和indexPath.row

两者没有实质区别,但是最好在 CollectionView中使用indexPath.item,tableView中使用indexPath.row,可以用来区别viewcontroller的不同。

五.collectionview 复用 导致( 数据重复 遮盖 残留)问题

这个问题很复杂,主流两种方法:

一是删除cell内的所有子视图(有时会不管用,可能是我视图没有移除干净。但是还是推荐,因为这才是真正的解决方法)

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
     NewTravelMediaCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
     for (id subView in cell.contentView.subviews) {
        if (subView){
            [subView removeFromSuperview];
        }
     }
    // cell 复用出来了。。这个cell 白白净净。接下来你想干嘛就干嘛
    // 如同上面我们所说的,cell 复用出来之后将子视图移除掉。再添加新的视图。这个方法我没试过,因为我之前就自定义好了cell 而且太多控件就没有去这样搞。
}

二是 取消cell的复用(数据大的话,不推荐)

 

参考链接:https://www.jianshu.com/p/fee6fbca2cff

参考链接:https://blog.csdn.net/wangyanchang21/article/details/78406299

参考链接:https://blog.csdn.net/u012108436/article/details/52200633

参考链接:https://www.jianshu.com/p/4ec50e0cb030

参考链接:https://www.jianshu.com/p/ed0d705eaef8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

app开发工程师V帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值