写在前面
这段时间都在忙新项目的事儿,没有时间倒腾,这两天闲下来,想着一直没有细细的研究CollectionView,一般最多用来做点循环滚动,所以花时间深入学习了一些东西,这次实现了CollectionView的拖动重排的效果,先请看图:(吐槽:不知道为啥从xcode7开始,模拟器变得很卡很卡,所以截图的效果不好,大家可以在真机上测试,效果还是非常不错的)
2月27日更新:
修复了拖拽滚动时抖动的一个bug,新增编辑模式,进入编辑模式后不用长按触发手势,且在开启抖动的情况下会自动进入抖动模式,如图:
![](http://file.zhishichong.com/images/article/20161028/005NFHyQgw1f5nk5798ocg308r0g5e81.gif)
图1:垂直滚动
![](http://file.zhishichong.com/images/article/20161028/005NFHyQgw1f5nk59spvqg308m0gawwn.gif)
图2:水平滚动
![](http://file.zhishichong.com/images/article/20161028/005NFHyQgw1f5nk5cm9tig308m0gahb3.gif)
图3:配合瀑布流(我直接使用了上个项目的瀑布流模块做了集成实验)
![](http://file.zhishichong.com/images/article/20161028/005NFHyQgw1f5nk5jn0s7g308m0gab2a.gif)
XWDragCellCollectionView
使用起来非常方便,github地址:可拖拽重排的CollectionView;使用也非常简单,只需3步,步骤如下:
1 2 3 4 5 6 7 |
1、继承于XWDragCellCollectionView; 2、实现必须实现的DataSouce代理方法:(在该方法中返回整个CollectionView的数据数组用于重排) - (NSArray *)dataSourceArrayOfCollectionView:(XWDragCellCollectionView *)collectionView; 3、实现必须实现的一个Delegate代理方法:(在该方法中将重拍好的新数据源设为当前数据源)(例如 :_data = newDataArray) - (void)dragCellCollectionView:(XWDragCellCollectionView *)collectionView newDataArrayAfterMove:(NSArray *)newDataArray; |
详细的使用可以查看代码中的demo,支持设置长按事件,是否开启边缘滑动,抖动、以及设置抖动等级,这些在h文件里面都有详细说明,有需要的可以尝试一下,并多多提意见,作为新手,肯定还有很多不足的地方;
原理
在刚刚考虑这个效果的时候,我仔细分析了一下效果,我首先想到的就是利用截图大法,将手指要移动的cell截个图来进行移动,并隐藏该cell,然后在合适的时候交换cell的位置,造成是拖拽cell被拖拽到新位置的效果,我将主要实现的步骤分为如下步骤:
1、给CollectionView添加一个长按手势,用于效果驱动
1 2 3 4 5 6 7 |
- (void)xwp_addGesture{ UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(xwp_longPressed:)]; _longPressGesture = longPress; //设置长按时间 longPress.minimumPressDuration = _minimumPressDuration; [self addGestureRecognizer:longPress]; } |
2、在手势开始的时候,得到手指所在的cell,并截图,并将原有cell隐藏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
- (void)xwp_gestureBegan:(UILongPressGestureRecognizer *)longPressGesture{ //获取手指所在的cell _originalIndexPath = [self indexPathForItemAtPoint:[longPressGesture locationOfTouch:0 inView:longPressGesture.view]]; UICollectionViewCell *cell = [self cellForItemAtIndexPath:_originalIndexPath]; //截图大法,得到cell的截图视图 UIView *tempMoveCell = [cell snapshotViewAfterScreenUpdates:NO]; _tempMoveCell = tempMoveCell; _tempMoveCell.frame = cell.frame; [self addSubview:_tempMoveCell]; //隐藏cell cell.hidden = YES; //记录当前手指位置 _lastPoint = [longPressGesture locationOfTouch:0 inView:longPressGesture.view]; } |
3、在手势移动的时候,计算出手势移动的距离,并移动截图视图,当截图视图于某一个cell(可见cell)相交到一定程度的时候,我就让调用系统的api交换这个cell和隐藏cell的位置,形成动画,同时更新数据源(更新数据源是最重要的操作!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
- (void)xwp_gestureChange:(UILongPressGestureRecognizer *)longPressGesture{ //计算移动距离 CGFloat tranX = [longPressGesture locationOfTouch:0 inView:longPressGesture.view].x - _lastPoint.x; CGFloat tranY = [longPressGesture locationOfTouch:0 inView:longPressGesture.view].y - _lastPoint.y; //设置截图视图位置 _tempMoveCell.center = CGPointApplyAffineTransform(_tempMoveCell.center, CGAffineTransformMakeTranslation(tranX, tranY)); _lastPoint = [longPressGesture locationOfTouch:0 inView:longPressGesture.view]; //计算截图视图和哪个cell相交 for (UICollectionViewCell *cell in [self visibleCells]) { 所以截图的效果不好,大家可以在真机上测试,效果还是非常不错的)
2月27日更新:修复了拖拽滚动时抖动的一个bug,新增编辑模式,进入编辑模式后不用长按触发手势,且在开启抖动的情况下会自动进入抖动模式,如图: ![]() 图1:垂直滚动![]() 图2:水平滚动![]() 图3:配合瀑布流(我直接使用了上个项目的瀑布流模块做了集成实验)![]() 我将整个控件进行了封装,名字是
XWDragCellCollectionView 使用起来非常方便,github地址:可拖拽重排的CollectionView;使用也非常简单,只需3步,步骤如下:
详细的使用可以查看代码中的demo,支持设置长按事件,是否开启边缘滑动,抖动、以及设置抖动等级,这些在h文件里面都有详细说明,有需要的可以尝试一下,并多多提意见,作为新手,肯定还有很多不足的地方; 原理在刚刚考虑这个效果的时候,我仔细分析了一下效果,我首先想到的就是利用截图大法,将手指要移动的cell截个图来进行移动,并隐藏该cell,然后在合适的时候交换cell的位置,造成是拖拽cell被拖拽到新位置的效果,我将主要实现的步骤分为如下步骤: 1、给CollectionView添加一个长按手势,用于效果驱动
2、在手势开始的时候,得到手指所在的cell,并截图,并将原有cell隐藏
3、在手势移动的时候,计算出手势移动的距离,并移动截图视图,当截图视图于某一个cell(可见cell)相交到一定程度的时候,我就让调用系统的api交换这个cell和隐藏cell的位置,形成动画,同时更新数据源(更新数据源是最重要的操作!)
|