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

Posted 吴彦祖666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 利用UICollectionView拖拽排序 实现的仿照腾讯新闻频道管理功能 XLChannelControl相关的知识,希望对你有一定的参考价值。

一、实现效果

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

             

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


1、大概思路

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

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;

为了实现Cell随手指移动的效果,这里需要添加一个辅助的_dragingCell,当定位好cell1后,把_dragingCell覆盖到cell1上,并添加一个放大动画。(_dragingCell伴随着手指移动而移动而不是cell1在移动)效果如下: 代码:
-(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是通过第一步定位操作获取的,用于保存正在被拖动cellindexPath; _targetIndexPath与当前被拖动cell交换位置的cell的indexPath; 当手指移动时,让_dragingCell跟随手指的移动而移动,从而找到_targetIndexPath,并让cell1cell2交换位置,交换位置后需要交换_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实现的,有兴趣的可以参考一下: 点我下载

以上是关于iOS 利用UICollectionView拖拽排序 实现的仿照腾讯新闻频道管理功能 XLChannelControl的主要内容,如果未能解决你的问题,请参考以下文章

iOS UICollectionView设置组背景色

iOS UICollectionView设置组背景色

iOS UICollectionView拖动排序

iOS 利用UICollectionView横向滚动余弦函数曲线特性实现居中放大的卡片浏览工具 XLCardSwitch

iOS UICollectionView 实现轮播图

iOS UICollectionView 实现轮播图