打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
iOS 利用UICollectionView拖拽排序 实现的仿照腾讯新闻频道管理功能 XLChannelControl

一、实现效果

     频道界面的显示 ------------》点击进行添加/删除--------》 按住可以进行拖拽排序

       
      

二、UICollectionView 拖拽排序的实现方法


1、大概思路

*拖拽排序的主要思路是利用在UICollectionView上添加一个长按的手势(UILongPressGestureRecognizer)实现的,实现步骤可以分三步:
第一步:通过长按操作找到需要被拖动的cell1
第二步:通过拖动cell1找到找到和它交换位置的cell2
第三步:交换cell1cell2的位置

2、具体的代码实现

1)、创建一个UICollectionView,然后给其添加一个长按手势

  1. -(void)buildUI
  2. {
  3. UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
  4. CGFloat cellWidth = (self.view.bounds.size.width - (ColumnNumber + 1) * CellMarginX)/ColumnNumber;
  5. flowLayout.itemSize = CGSizeMake(cellWidth,cellWidth);
  6. flowLayout.sectionInset = UIEdgeInsetsMake(0, CellMarginX, CellMarginY, CellMarginX);
  7. flowLayout.minimumLineSpacing = CellMarginY;
  8. flowLayout.minimumInteritemSpacing = CellMarginX;
  9. flowLayout.headerReferenceSize = CGSizeMake(self.view.bounds.size.width, 50);
  10. _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout];
  11. _collectionView.showsHorizontalScrollIndicator = false;
  12. _collectionView.backgroundColor = [UIColor clearColor];
  13. [_collectionView registerClass:[TestCell class] forCellWithReuseIdentifier:@"TestCell"];
  14. _collectionView.delegate = self;
  15. _collectionView.dataSource = self;
  16. [self.view addSubview:_collectionView];
  17. UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMethod:)];
  18. longPress.minimumPressDuration = 0.3f;
  19. [_collectionView addGestureRecognizer:longPress];
  20. _dragingCell = [[TestCell alloc] initWithFrame:CGRectMake(0, 0, cellWidth, cellWidth/2.0f)];
  21. _dragingCell.hidden = true;
  22. [_collectionView addSubview:_dragingCell];
  23. }

2)、利用UIGestureRecognizer在工作时的三种状态:开始、移动、停止这三种状态来分别实现三个主要功能

为了代码明了,分别创建三个方法,实现三个不同工能:
  1. -(void)longPressMethod:(UILongPressGestureRecognizer*)gesture
  2. {
  3. switch (gesture.state) {
  4. case UIGestureRecognizerStateBegan:
  5. [self dragBegin:gesture];
  6. break;
  7. case UIGestureRecognizerStateChanged:
  8. [self dragChanged:gesture];
  9. break;
  10. case UIGestureRecognizerStateEnded:
  11. [self dragEnd:gesture];
  12. break;
  13. default:
  14. break;
  15. }
  16. }
  17. -(void)dragBegin:(UILongPressGestureRecognizer*)gesture{
  18. }
  19. -(void)dragChanged:(UILongPressGestureRecognizer*)gesture{
  20. }
  21. -(void)dragEnd:(UILongPressGestureRecognizer*)gesture{
  22. }

第一步:UIGestureRecognizerStateBegan实现定位需要被拖拽的cell1并进入准备状态

定位cell1的方法,是通过手指定位在UICollectionView的点,来找到相应的cell:
  1. //获取被拖动IndexPath的方法
  2. -(NSIndexPath*)getDragingIndexPathWithPoint:(CGPoint)point
  3. {
  4. NSIndexPath* dragingIndexPath = nil;
  5. //遍历所有屏幕上的cell
  6. for (NSIndexPath *indexPath in [_collectionView indexPathsForVisibleItems]) {
  7. //判断cell是否包含这个点
  8. if (CGRectContainsPoint([_collectionView cellForItemAtIndexPath:indexPath].frame, point)) {
  9. dragingIndexPath = indexPath;
  10. break;
  11. }
  12. }
  13. return dragingIndexPath;
  14. }

为了实现Cell随手指移动的效果,这里需要添加一个辅助的_dragingCell,当定位好cell1后,把_dragingCell覆盖到cell1上,并添加一个放大动画。(让_dragingCell伴随着手指移动而移动而不是cell1在移动)效果如下:
代码:
  1. -(void)dragBegin:(UILongPressGestureRecognizer*)gesture{
  2. CGPoint point = [gesture locationInView:_collectionView];
  3. _dragingIndexPath = [self getDragingIndexPathWithPoint:point];
  4. if (!_dragingIndexPath) {return;}
  5. NSLog(@"拖拽开始 indexPath = %@",_dragingIndexPath);
  6. [_collectionView bringSubviewToFront:_dragingCell];
  7. //更新被拖拽的cell
  8. _dragingCell.frame = [_collectionView cellForItemAtIndexPath:_dragingIndexPath].frame;
  9. _dragingCell.hidden = false;
  10. [UIView animateWithDuration:0.3 animations:^{
  11. [_dragingCell setTransform:CGAffineTransformMakeScale(1.2, 1.2)];
  12. }];
  13. }

第二步:在UIGestureRecognizerStateChanged状态下找到即将与cell1交换位置的cell2并执行交换位置的动作

这里交换位置是通过手指的移动获取和cell1交换位置的cell2,这里定义了两个全局变量:
  1. //正在拖拽的indexpath
  2. NSIndexPath *_dragingIndexPath;
  3. //目标位置
  4. NSIndexPath *_targetIndexPath;
_dragingIndexPath是通过第一步定位操作获取的,用于保存正在被拖动cellindexPath;
_targetIndexPath与当前被拖动cell交换位置的cell的indexPath;
当手指移动时,让_dragingCell跟随手指的移动而移动,从而找到_targetIndexPath,并让cell1cell2交换位置,交换位置后需要交换_dragingIndexPath_targetIndexPath的值从而进行后续交换位置的操作。
定位_targetIndexPath的方法如下:
  1. //获取目标IndexPath的方法
  2. -(NSIndexPath*)getTargetIndexPathWithPoint:(CGPoint)point
  3. {
  4. NSIndexPath *targetIndexPath = nil;
  5. //遍历所有屏幕上的cell
  6. for (NSIndexPath *indexPath in _collectionView.indexPathsForVisibleItems) {
  7. //避免和当前拖拽的cell重复
  8. if ([indexPath isEqual:_dragingIndexPath]) {continue;}
  9. //判断是否包含这个点
  10. if (CGRectContainsPoint([_collectionView cellForItemAtIndexPath:indexPath].frame, point)) {
  11. targetIndexPath = indexPath;
  12. }
  13. }
  14. return targetIndexPath;
  15. }
拖拽_dragingCell并交换位置的方法如下:
  1. -(void)dragChanged:(UILongPressGestureRecognizer*)gesture{
  2. NSLog(@"拖拽中。。。");
  3. CGPoint point = [gesture locationInView:_collectionView];
  4. _dragingCell.center = point;
  5. _targetIndexPath = [self getTargetIndexPathWithPoint:point];
  6. NSLog(@"targetIndexPath = %@",_targetIndexPath);
  7. if (_targetIndexPath && _dragingIndexPath) {
  8. [_collectionView moveItemAtIndexPath:_dragingIndexPath toIndexPath:_targetIndexPath];
  9. _dragingIndexPath = _targetIndexPath;
  10. }
  11. }
效果如下:
第三步:UIGestureRecognizerStateEnded实现收尾工作

当手指离开屏幕拖拽结束时,隐藏_dragingCell,代码如下:
  1. -(void)dragEnd:(UILongPressGestureRecognizer*)gesture{
  2. NSLog(@"拖拽结束");
  3. if (!_dragingIndexPath) {return;}
  4. CGRect endFrame = [_collectionView cellForItemAtIndexPath:_dragingIndexPath].frame;
  5. [UIView animateWithDuration:0.3 animations:^{
  6. [_dragingCell setTransform:CGAffineTransformMakeScale(1.0, 1.0)];
  7. _dragingCell.frame = endFrame;
  8. }completion:^(BOOL finished) {
  9. _dragingCell.hidden = true;
  10. }];
  11. }
效果如下:


XLChannelControl GitHub地址


*之前写过一个版本是利用ScrollView实现的,有兴趣的可以参考一下:点我下载
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C# 操作鼠标移动到指定的屏幕位置方法
小米3如何移动、卸载和删除应用软件方法
移动屏幕式播放器”代码
移动屏幕式播放器”代码。
iOS布局和屏幕适配的一点总结
Google 为什么要把 Android 下面的三个按键规范为虚拟按键?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服