版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013282507/article/details/54374952
一、实现效果
频道界面的显示 ------------》点击进行添加/删除--------》 按住可以进行拖拽排序
二、UICollectionView 拖拽排序的实现方法
1、大概思路
*拖拽排序的主要思路是利用在UICollectionView上添加一个长按的手势(UILongPressGestureRecognizer)实现的,实现步骤可以分三步:
第一步:通过长按操作找到需要被拖动的cell1
第二步:通过拖动cell1找到找到和它交换位置的cell2
第三步:交换cell1和cell2的位置
2、具体的代码实现
1)、创建一个UICollectionView,然后给其添加一个长按手势
-(void)buildUI
{
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
CGFloat cellWidth = (self.view.bounds.size.width - (ColumnNumber + 1) * CellMarginX)/ColumnNumber;
flowLayout.itemSize = CGSizeMake(cellWidth,cellWidth);
flowLayout.sectionInset = UIEdgeInsetsMake(0, CellMarginX, CellMarginY, CellMarginX);
flowLayout.minimumLineSpacing = CellMarginY;
flowLayout.minimumInteritemSpacing = CellMarginX;
flowLayout.headerReferenceSize = CGSizeMake(self.view.bounds.size.width, 50);
_collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout];
_collectionView.showsHorizontalScrollIndicator = false;
_collectionView.backgroundColor = [UIColor clearColor];
[_collectionView registerClass:[TestCell class] forCellWithReuseIdentifier:@"TestCell"];
_collectionView.delegate = self;
_collectionView.dataSource = self;
[self.view addSubview:_collectionView];
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMethod:)];
longPress.minimumPressDuration = 0.3f;
[_collectionView addGestureRecognizer:longPress];
_dragingCell = [[TestCell alloc] initWithFrame:CGRectMake(0, 0, cellWidth, cellWidth/2.0f)];
_dragingCell.hidden = true;
[_collectionView addSubview:_dragingCell];
}
2)、利用UIGestureRecognizer在工作时的三种状态:开始、移动、停止这三种状态来分别实现三个主要功能
为了代码明了,分别创建三个方法,实现三个不同工能:
-(void)longPressMethod:(UILongPressGestureRecognizer*)gesture
{
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
[self dragBegin:gesture];
break;
case UIGestureRecognizerStateChanged:
[self dragChanged:gesture];
break;
case UIGestureRecognizerStateEnded:
[self dragEnd:gesture];
break;
default:
break;
}
}
-(void)dragBegin:(UILongPressGestureRecognizer*)gesture{
}
-(void)dragChanged:(UILongPressGestureRecognizer*)gesture{
}
-(void)dragEnd:(UILongPressGestureRecognizer*)gesture{
}
第一步:UIGestureRecognizerStateBegan实现定位需要被拖拽的cell1并进入准备状态
定位cell1的方法,是通过手指定位在UICollectionView的点,来找到相应的cell:
//获取被拖动IndexPath的方法
-(NSIndexPath*)getDragingIndexPathWithPoint:(CGPoint)point
{
NSIndexPath* dragingIndexPath = nil;
//遍历所有屏幕上的cell
for (NSIndexPath *indexPath in [_collectionView indexPathsForVisibleItems]) {
//判断cell是否包含这个点
if (CGRectContainsPoint([_collectionView cellForItemAtIndexPath:indexPath].frame, point)) {
dragingIndexPath = indexPath;
break;
}
}
return dragingIndexPath;
}
代码:
-(void)dragBegin:(UILongPressGestureRecognizer*)gesture{
CGPoint point = [gesture locationInView:_collectionView];
_dragingIndexPath = [self getDragingIndexPathWithPoint:point];
if (!_dragingIndexPath) {return;}
NSLog(@"拖拽开始 indexPath = %@",_dragingIndexPath);
[_collectionView bringSubviewToFront:_dragingCell];
//更新被拖拽的cell
_dragingCell.frame = [_collectionView cellForItemAtIndexPath:_dragingIndexPath].frame;
_dragingCell.hidden = false;
[UIView animateWithDuration:0.3 animations:^{
[_dragingCell setTransform:CGAffineTransformMakeScale(1.2, 1.2)];
}];
}
第二步:在UIGestureRecognizerStateChanged状态下找到即将与cell1交换位置的cell2并执行交换位置的动作
这里交换位置是通过手指的移动获取和cell1交换位置的cell2,这里定义了两个全局变量:
//正在拖拽的indexpath
NSIndexPath *_dragingIndexPath;
//目标位置
NSIndexPath *_targetIndexPath;
_dragingIndexPath是通过第一步定位操作获取的,用于保存正在被拖动cell的indexPath;
_targetIndexPath与当前被拖动cell交换位置的cell的indexPath;
当手指移动时,让_dragingCell跟随手指的移动而移动,从而找到_targetIndexPath,并让cell1和cell2交换位置,交换位置后需要交换_dragingIndexPath和_targetIndexPath的值从而进行后续交换位置的操作。
定位_targetIndexPath的方法如下:
//获取目标IndexPath的方法
-(NSIndexPath*)getTargetIndexPathWithPoint:(CGPoint)point
{
NSIndexPath *targetIndexPath = nil;
//遍历所有屏幕上的cell
for (NSIndexPath *indexPath in _collectionView.indexPathsForVisibleItems) {
//避免和当前拖拽的cell重复
if ([indexPath isEqual:_dragingIndexPath]) {continue;}
//判断是否包含这个点
if (CGRectContainsPoint([_collectionView cellForItemAtIndexPath:indexPath].frame, point)) {
targetIndexPath = indexPath;
}
}
return targetIndexPath;
}
拖拽_dragingCell并交换位置的方法如下:
-(void)dragChanged:(UILongPressGestureRecognizer*)gesture{
NSLog(@"拖拽中。。。");
CGPoint point = [gesture locationInView:_collectionView];
_dragingCell.center = point;
_targetIndexPath = [self getTargetIndexPathWithPoint:point];
NSLog(@"targetIndexPath = %@",_targetIndexPath);
if (_targetIndexPath && _dragingIndexPath) {
[_collectionView moveItemAtIndexPath:_dragingIndexPath toIndexPath:_targetIndexPath];
_dragingIndexPath = _targetIndexPath;
}
}
效果如下:
第三步:UIGestureRecognizerStateEnded实现收尾工作
当手指离开屏幕拖拽结束时,隐藏_dragingCell,代码如下:
-(void)dragEnd:(UILongPressGestureRecognizer*)gesture{
NSLog(@"拖拽结束");
if (!_dragingIndexPath) {return;}
CGRect endFrame = [_collectionView cellForItemAtIndexPath:_dragingIndexPath].frame;
[UIView animateWithDuration:0.3 animations:^{
[_dragingCell setTransform:CGAffineTransformMakeScale(1.0, 1.0)];
_dragingCell.frame = endFrame;
}completion:^(BOOL finished) {
_dragingCell.hidden = true;
}];
}
效果如下:
XLChannelControl GitHub地址
*之前写过一个版本是利用ScrollView实现的,有兴趣的可以参考一下:
点我下载