iOS9.0之后,UICollectionView多了两个代理方法,可以通过这俩个方法来对其上的item进行移动编辑,本文主要说下移动功能,移动前加了个抖动手势(类似APP删除时的抖动效果),然后拖动改变item的位置

- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPathNS_AVAILABLE_IOS(9_0);

9.0 之前的系统不可用,不过现在应该很少有9.0之前的系统了吧。

因为项目的原因,用到了这个,所以才有了本文;

在我们的项目中有这样一个需求,首页界面有三个模块,模块里有不同内容,可通过另外一个编辑界面对首页三个模块里内容的排列顺序进行编辑,编辑界面长按内容开始抖动,然后进行拖拽就行排序,重新排序后,返回首页,首页顺序改变,并且默认第一个内容不可改变(即房源大厅、客户跟进、我的门户不可编辑,永远在第一位),效果图如下:

1.排序前:

ios collectionview滑动到指定frame uicollectionview拖动排序_github

2.自定义应用功能,重新排序,改变资管和二手房等位置(这里的item其实是抖动的效果,图片上看不不出来,可从github上下载demo运行)

ios collectionview滑动到指定frame uicollectionview拖动排序_抖动动画_02

3.排序成功返回首页,首页的内容进行了改变,二手房等不见了 替换成新的内容

ios collectionview滑动到指定frame uicollectionview拖动排序_抖动动画_03


界面搭建就不多说了,说下主要的方法

/**
collectionView添加长按抖动手势
 */
-(void)addRecognize {
    
    if (!_recognize) {
        _recognize = [[UILongPressGestureRecognizeralloc] initWithTarget:selfaction:@selector(longPressGestureAction:)];
    }
    _recognize.minimumPressDuration =0.5;
    [self.collectionViewaddGestureRecognizer:_recognize];
}
/**
 *  添加长按拖动item的手势
 */
-(void)addLongGesture {
    
    if (_longGesture ==nil) {
        _longGesture = [[UILongPressGestureRecognizeralloc] initWithTarget:selfaction:@selector(handlelongGesture:)];
    }
    _longGesture.minimumPressDuration =0;
    [self.collectionViewaddGestureRecognizer:_longGesture];
}

/**
 *  长按手势
 */
-(void)startLongPress:(WXHome_AllAppCell *)cell {
    
    CABasicAnimation *animation = (CABasicAnimation *)[cell.layeranimationForKey:@"rotation"];
    if (animation ==nil) {
        [selfshakeImage:cell];
    }else{
        [selfresume:cell];
    }
}

// 复原
-(void)resume:(WXHome_AllAppCell *)cell {
    cell.layer.speed =1.0;
}

/** 动画 */
-(void)shakeImage:(WXHome_AllAppCell *)cell {
    
    CABasicAnimation *animation = [CABasicAnimationanimationWithKeyPath:@"transform.rotation.z"];
    [animation setDuration:0.1];
    animation.fromValue =@(-M_1_PI/6);
    animation.toValue =@(M_1_PI/6);
    animation.repeatCount =HUGE_VAL;
    animation.autoreverses =YES;
    cell.layer.anchorPoint =CGPointMake(0.5,0.5);
    [cell.layeraddAnimation:animation forKey:@"rotation"];
    
}
/**
 *  长按手势
 */
-(void)longPressGestureAction:(UILongPressGestureRecognizer *)longGesture {
    switch (longGesture.state) {
        caseUIGestureRecognizerStateBegan: {
            
            // 判断手势点是否在路径上
            NSIndexPath *indexPath = [self.collectionViewindexPathForItemAtPoint:[longGesturelocationInView:self.collectionView]];
            // 设置房源大厅不可移动
            if (indexPath.row >=0) {
                _isBegin =YES;
                [self.collectionViewremoveGestureRecognizer:_recognize];
                [selfaddLongGesture];
                [selfaddConfirmBtn];  // 这个是右上角的确定按钮,点击确定后,取消动画效果
                [self.collectionViewreloadData];
            }else {
                break;
            }
        }
            break;
        caseUIGestureRecognizerStateChanged: {}
            break;
        caseUIGestureRecognizerStateEnded: {}
            break;
        default:
            break;
    }
}

/**
 移动item
因为section分成了三块,所以首先要对section进行区分
 @param collectionView collectionView
 @param sourceIndexPath 开始
 @param destinationIndexPath 结束
 */
-(void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
    

    if (sourceIndexPath.section ==0) {
        
        id objc = [self.firstArrobjectAtIndex:sourceIndexPath.item];
        if (destinationIndexPath.section ==0) {
            [self.firstArrremoveObject:objc];
            [self.firstArrinsertObject:objc atIndex:destinationIndexPath.item];
        }else {
            [self.viewaddSubview:[ZLMNoticeLabelmessage:@"只能在同一功能里移动哦"delaySecond:2]];
        }
        
    }elseif (sourceIndexPath.section ==1) {
        
        id objc = [self.secondArrobjectAtIndex:sourceIndexPath.item];
        if (destinationIndexPath.section ==1) {
            [self.secondArrremoveObject:objc];
            [self.secondArrinsertObject:objc atIndex:destinationIndexPath.item];
        }else {
            [self.viewaddSubview:[ZLMNoticeLabelmessage:@"只能在同一功能里移动哦"delaySecond:2]];
        }
        
    }else {
        
        id objc = [self.thirdArrobjectAtIndex:sourceIndexPath.item];
        if (destinationIndexPath.section ==2) {
            [self.thirdArrremoveObject:objc];
            [self.thirdArrinsertObject:objc atIndex:destinationIndexPath.item];
        }else {
            [self.viewaddSubview:[ZLMNoticeLabelmessage:@"只能在同一功能里移动哦"delaySecond:2]];
        }
    }
}
 

 
 
 
/**
 *  长按拖动手势事件
 */
- (void)handlelongGesture:(UILongPressGestureRecognizer *)longGesture {
    
   staticNSInteger index =0;    // 记录section,防止跨section移动
    switch (longGesture.state) {
        caseUIGestureRecognizerStateBegan:{
            // 通过手势获取点,通过点获取点击的indexPath,移动该item
            NSIndexPath *AindexPath = [self.collectionViewindexPathForItemAtPoint:[longGesturelocationInView:self.collectionView]];
            if (AindexPath.row >0) {
// 我们项目中第一个item是不允许移动的,所以row从>0 开始,根据实际需求改写即可
                [self.collectionViewbeginInteractiveMovementForItemAtIndexPath:AindexPath];
                index = AindexPath.section;
            }else{
                break;
            }
        }
            break;
        caseUIGestureRecognizerStateChanged:{
            // 更新移动位置
            NSIndexPath *BindexPath = [self.collectionViewindexPathForItemAtPoint:[longGesturelocationInView:self.collectionView]];
            
            if (BindexPath.row<1) {
                break;
            }else {
                // 判断是否是同一section
                if (index == BindexPath.section) {
                    [self.collectionViewupdateInteractiveMovementTargetPosition:[longGesturelocationInView:self.collectionView]];
                }else {
                    [self.viewaddSubview:[ZLMNoticeLabelmessage:@"只能在同一功能里移动"delaySecond:3]];
                }
                
            }
            break;
        }
            break;
        caseUIGestureRecognizerStateEnded:
            // 移动完成关闭cell移动
            [self.collectionViewendInteractiveMovement];
            break;
            
        default:
            [self.collectionViewendInteractiveMovement];
            break;
    }
}