Swift - UICollectionView 长按拖拽

作者: coderLiu | 来源:发表于2017-03-10 10:41 被阅读1315次

    导读

    简单用Swift写了一个collectionview的拖拽点击排序效果;
    拖拽排序是新闻类的App可以说是必有的交互设计,如今日头条,网易新闻等。

    效果

    效果

    主要代码

    手势长按移动

    • 1.给CollectionViewCell添加一个长按手势.
    
    private lazy var collectionView: UICollectionView = {
    
            let clv = UICollectionView(frame: self.view.frame, collectionViewLayout: ChannelViewLayout())
            clv.backgroundColor = UIColor.white
            clv.delegate = self
            clv.dataSource = self
            clv.register(ChannelViewCell.self, forCellWithReuseIdentifier: ChannelViewCellIdentifier)
            clv.register(ChannelHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: ChannelViewHeaderIdentifier)
            let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPressGesture(_:)))
            clv.addGestureRecognizer(longPress)
            
            return clv
        }()
    
    • 2.开始长按时对cell进行截图或拷贝一个cell,并隐藏cell.
        //MARK: - 长按开始
        private func dragBegan(point: CGPoint) {
            
            indexPath = collectionView.indexPathForItem(at: point)
            if indexPath == nil || (indexPath?.section)! > 0 || indexPath?.item == 0
            {return}
            
            let item = collectionView.cellForItem(at: indexPath!) as? ChannelViewCell
            item?.isHidden = true
            dragingItem.isHidden = false
            dragingItem.frame = (item?.frame)!
            dragingItem.text = item!.text
            //放大效果(此处可以根据需求随意修改)
            dragingItem.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
            
        }
    
    
    • 3.在手势移动的时候,找到目标是的indexPatch,再调用系统的api交换这个cell和隐藏cell的位置,并且更新数据.
        //MARK: - 移动过程
        private func drageChanged(point: CGPoint) {
    
            if indexPath == nil || (indexPath?.section)! > 0 || indexPath?.item == 0 {return}
            dragingItem.center = point
            targetIndexPath = collectionView.indexPathForItem(at: point)
            if targetIndexPath == nil || (targetIndexPath?.section)! > 0 || indexPath == targetIndexPath || targetIndexPath?.item == 0 {return}
            // 更新数据
            let obj = selectedArr[indexPath!.item]
            selectedArr.remove(at: indexPath!.row)
            selectedArr.insert(obj, at: targetIndexPath!.item)
            //交换位置
            collectionView.moveItem(at: indexPath!, to: targetIndexPath!)
            //进行记录
            indexPath = targetIndexPath
    
        }
    
    
    • 4.手势停止或取消时,移除view,显示隐藏cell. (这里手势取消也要掉用此方法)
    //MARK: - 长按结束或取消
        private func drageEnded(point: CGPoint) {
            
            if indexPath == nil || (indexPath?.section)! > 0 || indexPath?.item == 0 {return}
            let endCell = collectionView.cellForItem(at: indexPath!)
            
            UIView.animate(withDuration: 0.25, animations: {
            
                self.dragingItem.transform = CGAffineTransform.identity
                self.dragingItem.center = (endCell?.center)!
                
            }, completion: {
            
                (finish) -> () in
                
                endCell?.isHidden = false
                self.dragingItem.isHidden = true
                self.indexPath = nil
                
            })
            
        }
    
    

    点击移动

    • collectionView的点击方法,我这里分为两段,第一段为点击处理事件,第二段为点击添加添加标签(编辑状态下第一段可以点击排序)
       func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            
            
            
            if indexPath.section > 0 {
                
                // 更新数据
                let obj = recommendArr[indexPath.item]
                recommendArr.remove(at: indexPath.item)
                selectedArr.append(obj)
                //移动方法
                collectionView.moveItem(at: indexPath, to: NSIndexPath(item: selectedArr.count - 1, section: 0) as IndexPath)
                
            } else {
                
                if isEdite {
                    
                    if indexPath.item == 0 {return}
                    // 更新数据
                    let obj = selectedArr[indexPath.item]
                    selectedArr.remove(at: indexPath.item)
                    recommendArr.insert(obj, at: 0)
                    //移动方法
                    collectionView.moveItem(at: indexPath, to: NSIndexPath(item: 0, section: 1) as IndexPath)
                    
                } else {
                    
                    if switchoverCallback != nil {
                        //处理点击的闭包
                        switchoverCallback!(selectedArr, recommendArr, indexPath.item)
                        _ = navigationController?.popViewController(animated: true)
                    }
                }
            }
            
            
            
        }
    

    其他

    此代码只是一个效果,没有怎么封装,如果仔细看过的朋友可以知道其实没有多么复杂

    • 点击移动
    collectionView.moveItem(at: indexPath, to: NSIndexPath(item: 0, section: 1) as IndexPath)
    
    • 拖拽移动
    collectionView.moveItem(at: indexPath!, to: targetIndexPath!)
    

    主要就是这两个方法,其他都是处理逻辑以及视图效果.

    提示

    如果你们是从iOS9开始适配的话,那么可以用系统的Api,非常简单好用,大家这里可以自己去试试.

        // Support for reordering
        @available(iOS 9.0, *)
        open func beginInteractiveMovementForItem(at indexPath: IndexPath) -> Bool // returns NO if reordering was prevented from beginning - otherwise YES
    
        @available(iOS 9.0, *)
        open func updateInteractiveMovementTargetPosition(_ targetPosition: CGPoint)
    
        @available(iOS 9.0, *)
        open func endInteractiveMovement()
    
        @available(iOS 9.0, *)
        open func cancelInteractiveMovement()
    

    相关文章

      网友评论

      • 4ae4223a0fae:很喜欢你这个,我项目也需要和你一摸一样的,不过swift版本的我不懂:sweat: ,你有OC版本吗?急需,谢谢
        coderLiu:你看看这个行吗 https://github.com/mengxianliang/XLChannelControl
      • 4ae4223a0fae:你好,你这个有OC版本的吗?

      本文标题:Swift - UICollectionView 长按拖拽

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