美文网首页
iOS - UICollectionView 长按拖拽单元格

iOS - UICollectionView 长按拖拽单元格

作者: iOS小菜鸟一枚 | 来源:发表于2018-12-25 16:13 被阅读0次

    一、先上gif效果图,DEMO链接:https://gitee.com/xudongxiang/DragDropCollectionView.git

    201812251450165.gif

    二、代码实现细节

    1. 初始化collectionView,以及遵守UICollectionViewDelegate、UICollectionViewDataSource ,并且注册cell等一波常规操作

    UICollectionViewFlowLayout *collectionFlowLayout = [[UICollectionViewFlowLayout alloc] init];
    collectionFlowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 375, 667) collectionViewLayout:collectionFlowLayout];
    self.collectionView.backgroundColor = [UIColor whiteColor];
    [self.collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;
    [self.view addSubview:self.collectionView];
    

    2. 为collectionView添加长按手势

    // 添加长按抖动手势
    [self addRecognize];
    
    - (void)addRecognize
    {
        UILongPressGestureRecognizer *recognize = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureAction:)];
        
        //设置长按响应时间为0.5秒
        recognize.minimumPressDuration = 0.5;   
        
        [self.collectionView addGestureRecognizer:recognize];
    }
    

    3. 实现长按后collectionView的抖动效果,并且为collectionView添加拖动手势

    // 长按抖动手势方法
    - (void)longPressGestureAction:(UILongPressGestureRecognizer *)longGesture {
        switch (longGesture.state) {
            case UIGestureRecognizerStateBegan: {
            
                // 移除长按手势
                [self.collectionView removeGestureRecognizer:longGesture];
                
                // 为collectionView添加拖动手势
                [self addGesture];
                
                 // 用一个BOOL类型的全局变量,记录collectionView是否为抖动状态,YES:抖动,NO:停止抖动
                _isItemShake = YES; 
                [self.collectionView reloadData];
            }
                break;
            case UIGestureRecognizerStateChanged: {}
                break;
            case UIGestureRecognizerStateEnded: {}
                break;
            default:
                break;
        }
    }
    
    - (void)addGesture
    {
        UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlelongGesture:)];
        longGesture.minimumPressDuration = 0;
        [self.collectionView addGestureRecognizer:longGesture];
    }
    

    4. 实现collectionView的拖动效果,下面会使用iOS9的新特性实现拖拽,必须调用UICollectionView的下面两个方法

    // 开始移动的时候调用此方法,可以获取相应的datasource方法设置特殊的indexpath 能否移动,如果能移动返回的是YES ,不能移动返回的是NO
    - (BOOL)beginInteractiveMovementForItemAtIndexPath:(NSIndexPath *)indexPath
    
    // 更新移动过程的位置
    - (void)updateInteractiveMovementTargetPosition:(CGPoint)targetPosition 
    
    // 长按抖动手势方法
    - (void)handlelongGesture:(UILongPressGestureRecognizer *)longGesture {
        switch (longGesture.state) {
            case UIGestureRecognizerStateBegan:{
            
                // 通过手势获取点,通过点获取点击的indexPath, 移动该cell
                NSIndexPath *aIndexPath = [self.collectionView indexPathForItemAtPoint:[longGesture locationInView:self.collectionView]];
                [self.collectionView beginInteractiveMovementForItemAtIndexPath:aIndexPath];
                
            }
                break;
            case UIGestureRecognizerStateChanged:{
                
                // 通过手势获取点,通过点获取拖动到的indexPath, 更新该cell位置
                [self.collectionView updateInteractiveMovementTargetPosition:[longGesture locationInView:self.collectionView]];
                
            }
                break;
            case UIGestureRecognizerStateEnded:{
            
                // 移动完成关闭cell移动
                [self.collectionView endInteractiveMovement];
    
            // 移除拖动手势
                [self.collectionView removeGestureRecognizer:longGesture];
    
                // collectionView停止抖动
                _isItemShake = NO;
                
                // 为collectionView添加拖动手势
                [self addRecognize];
                
                NSArray *cellArray = [self.collectionView visibleCells];
                for (CollectionViewCell *cell in cellArray ) {
                    // 调用cell停止抖动方法
                    [cell stopShake];
                }
            }
                break;
            default:
                [self.collectionView endInteractiveMovement];
                [self.collectionView removeGestureRecognizer:longGesture];
                _isItemShake = NO;
                [self addRecognize];
                NSArray *cellArray = [self.collectionView visibleCells];
                for (CollectionViewCell *cell in cellArray ) {
                    [cell stopShake];
                }
                break;
        }
    }
    

    5. 实现UICollectionViewDelegate、UICollectionViewDataSource

    - (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
    {
        return YES;
    }
    
    - (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
    {
        // 删除数据源中初始位置的数据
        id objc = [self.colorArray objectAtIndex:sourceIndexPath.item];
        [self.colorArray removeObject:objc];
    
        // 将数据插入数据源中新的位置,实现数据源的更新
        [self.colorArray insertObject:objc atIndex:destinationIndexPath.item];
        
        NSArray *cellArray = [self.collectionView visibleCells];
        for (CollectionViewCell *cell in cellArray ) {
            [cell stopShake];
        }
    }
    
    //配置cell大小
    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        return CGSizeMake(167, 167);
    }
    
    //配置行间距
    - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
    {
        return 15;
    }
    
    //配置每组上下左右的间距
    - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
    {
        return UIEdgeInsetsMake(0, 13, 15, 13);
    }
    
    #pragma mark - UICollectionViewDataSource
    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
    {
        return 1;
    }
    
    //配置每个组里面有多少个cell
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
        return self.colorArray.count;
    }
    //配置cell,并且通过_isItemShake控制cell是否抖动
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
        [cell loadWithModel:self.colorArray[indexPath.row] ];
        if (_isItemShake) {
        
        // 调用cell开始抖动方法
            [cell beginShake];
            
        }else{
        
            // 调用cell停止抖动方法
            [cell stopShake];
            
        }
        return cell;
    }
    

    6. 在CollectionViewCell.m文件中实现cell的抖动和停止抖动方法

    // 实现cell抖动方法
    - (void)beginShake
    {
        CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
        anim.keyPath = @"transform.rotation";
        anim.duration = 0.2;
        anim.repeatCount = MAXFLOAT;
        anim.values = @[@(-0.03),@(0.03),@(-0.03)];
        anim.removedOnCompletion = NO;
        anim.fillMode = kCAFillModeForwards;
        [self.layer addAnimation:anim forKey:@"shake"];
    }
    
    // 实现cell停止抖动方法
    - (void)stopShake
    {
        [self.layer removeAllAnimations];
    }
    

    相关文章

      网友评论

          本文标题:iOS - UICollectionView 长按拖拽单元格

          本文链接:https://www.haomeiwen.com/subject/xavflqtx.html