写在前面:
调用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