CollectionView实现频道编辑
UICollectionView布局
分为上下两个section
为cell添加长按和拖拽手势
根据位置重叠来判断拖拽位置
分为不同的情况来处理数据源
目标效果图
实现步骤
UICollectionView 布局
UICollectionView 初始化
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
UICollectionViewFlowLayout
使用默认的流式布局
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
//设置行距
layout.minimumLineSpacing = 10;
//设置列距
layout.minimumInteritemSpacing = 10;
//设置每个 item 的大小
layout.itemSize = CGSizeMake((ScreenWidth / 4) - 20 , 30);
//设置 item 的上左下右的边距大小
layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
ColletionView属性
| BOOL showsHorizontalScrollIndicator | 控制是否显示水平方向的滚动条 |
| ----------------------------------- | -------------------------------- |
| BOOL directionalLockEnabled | 指定控件是否只能在一个方向上滚动 |
| BOOL alwaysBounceVertical | 控制垂直方向遇到边框是否反弹 |
| BOOL alwaysBounceHorizontal | 控制水平方向遇到边框是否反弹 |
注册
[_collectionView registerClass:[ChannelCollectionViewCell class] forCellWithReuseIdentifier:NSStringFromClass([ChannelCollectionViewCell class])];
[_collectionView registerClass:[HeaderReusableView class]forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:NSStringFromClass([HeaderReusableView class])];
注意 为cell 和section头 注册要与代理方法中保持一致
CollectionView代理方法
//返回 section的个数
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
//返回每个section中cell的个数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
//返回 具体的cell
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
//返回 section的 headerView
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
//返回每个section 的headerView大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
//点击cell触发的方法
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
自定义cell
为cell添加 长按 和 拖拽 手势
- (void)addGestureRecognizer {
//长按手势
UILongPressGestureRecognizer * longPress =[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(gestureAction:)];
longPress.delegate = self;
[self addGestureRecognizer:longPress];
//拖拽手势
UIPanGestureRecognizer * pan =[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(gestureAction:)];
pan.delegate = self;
[self addGestureRecognizer:pan];
}
定义协议 让代理为cell实现 手势事件
@protocol ChannelCollectionViewCellDelegate <NSObject>
- (void)CellGestureAction:(UIGestureRecognizer *) gestureRecognizer;
- (void)CellCancel:(ChannelCollectionViewCell *) Cell;
@end
在VC里面实现代理方法
- (void)CellGestureAction:(UIGestureRecognizer *)gestureRecognizer {
//伪代码
记录当前cell的位置 和cell;
if (识别手势开始) {
if (是长按手势){
进入编辑状态;
}
if (是编辑状态) {
return;
}
} else if (手势改变) {
使用截图View 替代当前的cell的View
不同section之间cell的拖动分不同的情况处理数据源
} else if (手势停止) {
移除截图View;
显示原来的cell;
}
}
难点
拖拽的实现
数据源的处理
解决方案 : 拖拽计算截图cell 和拖拽位置cell 的中心点 ,只要截图cell的中心点进入了其他cell范围中,就实现位置移动 ,改变数据源
上下section数据联动需要根据情况 采取不同的方法处理数据源
遗留问题
拖拽到边缘时,collectionView不会自动滚动
预想解决方案: 当拖拽到边缘时 , 添加定时器, 改变CollectionView的contentoffset