collectionView技巧

  • 组头、组尾
  • item的重排问题
  • sectionInset内边距
  • 自定义Layout
  • 第三方CHTCollectionViewWaterfallLayout的使用

组头、组尾

//每段的段头视图,或者段尾视图
-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
        HJCollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"headerView" forIndexPath:indexPath];
        SWPWikiModel *wikiModel = self.dataSourceArray[indexPath.section];
        view.backgroundColor = [UIColor whiteColor];
        if ([wikiModel.kind isEqualToString:@"group"]) {
            view.kindLabel.text =  @"食物类别";
        }else if ([wikiModel.kind isEqualToString:@"brand"]) {
            view.kindLabel.text =  @"热门品牌";
        }else if ([wikiModel.kind isEqualToString:@"restaurant"]) {
            view.kindLabel.text =  @"连锁餐饮";
        }else{
            view.kindLabel.text =  @"其他类别";
        }
        
        return view;
    }else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
        HJCollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"footerView" forIndexPath:indexPath];
        view.backgroundColor = [UIColor colorWithRed:218/256.0 green:218/256.0 blue:218/256.0 alpha:1];
        view.kindLabel.backgroundColor = [UIColor colorWithRed:218/256.0 green:218/256.0 blue:218/256.0 alpha:1];
        return view;
    }
    return nil;
}

item的重排问题

  1. 添加长按手势UILongpressGestureRecognizer
-(void)addLongPressGestureToCollectionView{
        UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc]initWithTarget:self      action:@selector(longPressHandle:)];
        [self.collectionView addGestureRecognizer:longPressGesture];
}
  1. 监听手势状态state变化
1.beginInteractiveMovementForItemAtIndexPath: //开始移动
2.updateInteractiveMovementTargetPosition:       //更新坐标
3.endInteractiveMovement:                                    //结束移动
4.cancelInteractiveMovement:                                //取消移动
  1. dataSourceArray删除、添加数据
第三步:dataSourceArray删除,插入数据
#pragma mark - Action
 /*cell的移动(从oldindex 移到 newindex)*/
 -(void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath: (NSIndexPath *)destinationIndexPath{
//0.获取移动的起点和终点
       NSInteger from = sourceIndexPath.item;
       NSInteger to = destinationIndexPath.item;
       //1.获取要删除的数据
       NSString *o = self.datasourceArray[from];    
       //2.删除要移动的数据
       [self.datasourceArray removeObjectAtIndex:from];    
       //3.插入指定的位置
       [self.datasourceArray insertObject:o atIndex:to];
}

sectionInset内边距

collectionView技巧_第1张图片
dd.png

自定义Layout

  1. 边界改变是否让布局无效
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
    return YES;
}
  1. 准备布局
/*
 *注释:第一步
 *  1.实例化时最开始调用这个方法,
 *  2.布局无效之后
 *  3.查询布局信息之前
 *  4.如果子类覆盖(重写方法),子类应该总是调用super。invalidateLayout布局无效
 *  5.在这里面一般就是写collectionView、cell。。配置信息(itemSize,间距等)
 */
-(void)prepareLayout
{
    [super prepareLayout];
    //滚动方向
    self.scrollDirection = UICollectionViewScrollDirectionVertical;
    //设置collectionView内边距
    CGFloat insert = (self.collectionView.frame.size.width - self.itemSize.width) / 2;
    self.sectionInset = UIEdgeInsetsMake(insert, insert, insert, insert);
}
  1. 返回滚动后推荐的停留点(偏移量)
/*
 *注释:第二步
 *
 *返回滚动后推荐(proposed)停止的点(偏移量),在这里要进行处理
 */
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
    //计算最终显示的边界
    CGRect rect;
    rect.origin.x = proposedContentOffset.x;
    rect.origin.y = 0;
    rect.size = self.collectionView.frame.size;
    // 获得所有显示区域内的布局对象
    NSArray *arr = [super layoutAttributesForElementsInRect:rect];
    // collectionView中心点的x值 、 偏移量 + 一半宽度 = 当前collectionView的中点对应着contentView的哪一个中点
    CGFloat contentCenterX = self.collectionView.frame.size.width / 2 + proposedContentOffset.x;
    //存放布局对象数组中离(上面计算的)的点最小间距的布局对象的距离
    CGFloat minDistance = MAXFLOAT;
    for (UICollectionViewLayoutAttributes * attr in arr) {
        CGFloat distance = ABS(attr.center.x - contentCenterX);
        minDistance = minDistance > distance ? distance : minDistance;
    }
    //处理推荐的点,达到每次都停在图片中间的效果(之所以明确是➕,因为偏移一定是负数)
    proposedContentOffset.x += minDistance;
    return proposedContentOffset;
}
  1. 重新布局可视范围视图内的所有子控件
/*
 *注释:第三步:重新布局所有子控件cell
 *
 *作用相当于layoutSubViews,最后才执行的
 */
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    //先布局super,只有流体布局才能使用
    NSArray *arr = [super layoutAttributesForElementsInRect:rect];
    
    //计算contentView中心点
    CGFloat contentCenterX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width / 2;
    
    for (UICollectionViewLayoutAttributes *attr in arr) {
        //求contentView的中心点和cell的中心点的距离[ABS:取绝对值]
        CGFloat distance = ABS(attr.center.x - contentCenterX);//比不理解。。。。。。。。。。。。。。
        //根据间距,计算缩放比例,
        CGFloat scale = 1 - distance / self.collectionView.frame.size.width;
        //设置cell的显示比例(当cell正好处于collectionView中点)
        attr.transform = CGAffineTransformMakeScale(scale, scale);
    }
    return arr;
}

第三方CHTCollectionViewWaterfallLayout的使用

  • 组头、组尾
  • 必须实现的代理方法,确定itemSize
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
  UICollectionReusableView *reusableView = nil;

  if ([kind isEqualToString:CHTCollectionElementKindSectionHeader]) {
    reusableView = [collectionView dequeueReusableSupplementaryViewOfKind:kind
                                                      withReuseIdentifier:HEADER_IDENTIFIER
                                                             forIndexPath:indexPath];
  } else if ([kind isEqualToString:CHTCollectionElementKindSectionFooter]) {
    reusableView = [collectionView dequeueReusableSupplementaryViewOfKind:kind
                                                      withReuseIdentifier:FOOTER_IDENTIFIER
                                                             forIndexPath:indexPath];
  }

  return reusableView;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
  return [self.cellSizes[indexPath.item] CGSizeValue];
}

你可能感兴趣的:(collectionView技巧)