如何实现UITableView的滑动以删除UICollectionView

Miu*_*Miu 18 uitableview ios uicollectionview

我想问一下如何在UICollectionView中实现UITableView滑动删除的相同行为.我试图找到一个教程,但我找不到任何.

另外,我使用PSTCollectionView包装器来支持iOS 5.

谢谢!

编辑:滑动识别器已经很好了.我现在需要的是取消删除模式时与UITableView相同的功能,例如当用户点击单元格或表格视图中的空白区域时(即,当用户点击删除按钮之外时).UITapGestureRecognizer不起作用,因为它只检测触摸释放时的点击.UITableView在手势开始时(而不是在释放时)检测到触摸,并立即取消删除模式.

小智 13

iOS的" 集合视图编程指南"中,在" 合并手势支持 "一节中,文档内容如下:

您应始终将手势识别器附加到集合视图本身,而不是附加到特定单元格或视图.

所以,我认为添加识别器不是一个好习惯UICollectionViewCell.


LC *_*C 웃 13

它非常简单..你需要添加一个customContentViewcustomBackgroundView后面的customContentView.

之后,customContentView当用户从右向左滑动时,您需要向左移动.移动视图使得可见customBackgroundView.

让代码:

首先,你需要将panGesture添加到你的UICollectionViewas

   override func viewDidLoad() {
        super.viewDidLoad()
        self.panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panThisCell))
        panGesture.delegate = self
        self.collectionView.addGestureRecognizer(panGesture)

    }
Run Code Online (Sandbox Code Playgroud)

现在将选择器实现为

  func panThisCell(_ recognizer:UIPanGestureRecognizer){

        if recognizer != panGesture{  return }

        let point = recognizer.location(in: self.collectionView)
        let indexpath = self.collectionView.indexPathForItem(at: point)
        if indexpath == nil{  return }
        guard let cell = self.collectionView.cellForItem(at: indexpath!) as? CustomCollectionViewCell else{

            return

        }
        switch recognizer.state {
        case .began:

            cell.startPoint =  self.collectionView.convert(point, to: cell)
            cell.startingRightLayoutConstraintConstant  = cell.contentViewRightConstraint.constant
            if swipeActiveCell != cell && swipeActiveCell != nil{

                self.resetConstraintToZero(swipeActiveCell!,animate: true, notifyDelegateDidClose: false)
            }
            swipeActiveCell = cell

        case .changed:

            let currentPoint =  self.collectionView.convert(point, to: cell)
            let deltaX = currentPoint.x - cell.startPoint.x
            var panningleft = false

            if currentPoint.x < cell.startPoint.x{

                panningleft = true

            }
            if cell.startingRightLayoutConstraintConstant == 0{

                if !panningleft{

                    let constant = max(-deltaX,0)
                    if constant == 0{

                        self.resetConstraintToZero(cell,animate: true, notifyDelegateDidClose: false)

                    }else{

                        cell.contentViewRightConstraint.constant = constant

                    }
                }else{

                    let constant = min(-deltaX,self.getButtonTotalWidth(cell))
                    if constant == self.getButtonTotalWidth(cell){

                        self.setConstraintsToShowAllButtons(cell,animate: true, notifyDelegateDidOpen: false)

                    }else{

                        cell.contentViewRightConstraint.constant = constant
                        cell.contentViewLeftConstraint.constant = -constant
                    }
                }
            }else{

                let adjustment = cell.startingRightLayoutConstraintConstant - deltaX;
                if (!panningleft) {

                    let constant = max(adjustment, 0);
                    if (constant == 0) {

                        self.resetConstraintToZero(cell,animate: true, notifyDelegateDidClose: false)

                    } else {

                        cell.contentViewRightConstraint.constant = constant;
                    }
                } else {
                    let constant = min(adjustment, self.getButtonTotalWidth(cell));
                    if (constant == self.getButtonTotalWidth(cell)) {

                        self.setConstraintsToShowAllButtons(cell,animate: true, notifyDelegateDidOpen: false)
                    } else {

                        cell.contentViewRightConstraint.constant = constant;
                    }
                }
                cell.contentViewLeftConstraint.constant = -cell.contentViewRightConstraint.constant;

            }
            cell.layoutIfNeeded()
        case .cancelled:

            if (cell.startingRightLayoutConstraintConstant == 0) {

                self.resetConstraintToZero(cell,animate: true, notifyDelegateDidClose: true)

            } else {

                self.setConstraintsToShowAllButtons(cell,animate: true, notifyDelegateDidOpen: true)
            }

        case .ended:

            if (cell.startingRightLayoutConstraintConstant == 0) {
                //Cell was opening
                let halfOfButtonOne = (cell.swipeView.frame).width / 2;
                if (cell.contentViewRightConstraint.constant >= halfOfButtonOne) {
                    //Open all the way
                    self.setConstraintsToShowAllButtons(cell,animate: true, notifyDelegateDidOpen: true)
                } else {
                    //Re-close
                    self.resetConstraintToZero(cell,animate: true, notifyDelegateDidClose: true)
                }
            } else {
                //Cell was closing
                let buttonOnePlusHalfOfButton2 = (cell.swipeView.frame).width
                if (cell.contentViewRightConstraint.constant >= buttonOnePlusHalfOfButton2) {
                    //Re-open all the way
                    self.setConstraintsToShowAllButtons(cell,animate: true, notifyDelegateDidOpen: true)
                } else {
                    //Close
                    self.resetConstraintToZero(cell,animate: true, notifyDelegateDidClose: true)
                }
            }

        default:
            print("default")
        }
    }
Run Code Online (Sandbox Code Playgroud)

Helper更新约束的方法

 func getButtonTotalWidth(_ cell:CustomCollectionViewCell)->CGFloat{

        let width = cell.frame.width - cell.swipeView.frame.minX
        return width

    }

    func resetConstraintToZero(_ cell:CustomCollectionViewCell, animate:Bool,notifyDelegateDidClose:Bool){

        if (cell.startingRightLayoutConstraintConstant == 0 &&
            cell.contentViewRightConstraint.constant == 0) {
            //Already all the way closed, no bounce necessary
            return;
        }
        cell.contentViewRightConstraint.constant = -kBounceValue;
        cell.contentViewLeftConstraint.constant = kBounceValue;
        self.updateConstraintsIfNeeded(cell,animated: animate) {
            cell.contentViewRightConstraint.constant = 0;
            cell.contentViewLeftConstraint.constant = 0;

            self.updateConstraintsIfNeeded(cell,animated: animate, completionHandler: {

                cell.startingRightLayoutConstraintConstant = cell.contentViewRightConstraint.constant;
            })
        }
        cell.startPoint = CGPoint()
        swipeActiveCell = nil
    }

    func setConstraintsToShowAllButtons(_ cell:CustomCollectionViewCell, animate:Bool,notifyDelegateDidOpen:Bool){

        if (cell.startingRightLayoutConstraintConstant == self.getButtonTotalWidth(cell) &&
            cell.contentViewRightConstraint.constant == self.getButtonTotalWidth(cell)) {
            return;
        }
        cell.contentViewLeftConstraint.constant = -self.getButtonTotalWidth(cell) - kBounceValue;
        cell.contentViewRightConstraint.constant = self.getButtonTotalWidth(cell) + kBounceValue;

        self.updateConstraintsIfNeeded(cell,animated: animate) {
            cell.contentViewLeftConstraint.constant =  -(self.getButtonTotalWidth(cell))
            cell.contentViewRightConstraint.constant = self.getButtonTotalWidth(cell)

            self.updateConstraintsIfNeeded(cell,animated: animate, completionHandler: {(check) in

                cell.startingRightLayoutConstraintConstant = cell.contentViewRightConstraint.constant;
            })
        }
    }

    func setConstraintsAsSwipe(_ cell:CustomCollectionViewCell, animate:Bool,notifyDelegateDidOpen:Bool){

        if (cell.startingRightLayoutConstraintConstant == self.getButtonTotalWidth(cell) &&
            cell.contentViewRightConstraint.constant == self.getButtonTotalWidth(cell)) {
            return;
        }
        cell.contentViewLeftConstraint.constant = -self.getButtonTotalWidth(cell) - kBounceValue;
        cell.contentViewRightConstraint.constant = self.getButtonTotalWidth(cell) + kBounceValue;

        self.updateConstraintsIfNeeded(cell,animated: animate) {
            cell.contentViewLeftConstraint.constant =  -(self.getButtonTotalWidth(cell))
            cell.contentViewRightConstraint.constant = self.getButtonTotalWidth(cell)

            self.updateConstraintsIfNeeded(cell,animated: animate, completionHandler: {(check) in

                cell.startingRightLayoutConstraintConstant = cell.contentViewRightConstraint.constant;
            })
        }
    }


    func updateConstraintsIfNeeded(_ cell:CustomCollectionViewCell, animated:Bool,completionHandler:@escaping ()->()) {
        var duration:Double = 0
        if animated{

            duration = 0.1

        }
        UIView.animate(withDuration: duration, delay: 0, options: [.curveEaseOut], animations: {

            cell.layoutIfNeeded()

            }, completion:{ value in

                if value{ completionHandler() }
        })
    }
Run Code Online (Sandbox Code Playgroud)

我创建了一个示例项目在这里斯威夫特3.

它是本教程的修改版本.


Ame*_*kic 10

您的问题有一个更简单的解决方案,可以避免使用手势识别器.该解决方案基于UIScrollView与之相结合UIStackView.

  1. 首先,您需要创建2个容器视图 - 一个用于单元格的可见部分,另一个用于隐藏部分.您将这些视图添加到UIStackView.该stackView会作为一个内容视图.确保视图具有相等的宽度stackView.distribution = .fillEqually.

  2. 你将嵌入stackView一个UIScrollView启用了分页的内部.的scrollView应限制在小区的边缘.然后,您将stackView宽度设置为宽度的2倍,scrollView这样每个容器视图都将具有单元格的宽度.

通过这个简单的实现,您创建了具有可见和隐藏视图的基本单元.使用可见视图向单元格添加内容,在隐藏视图中添加删除按钮.这样你就可以实现这个目的:

滑动即可删除

在GitHub上设置了一个示例项目.您还可以在此处详细了解此解决方案.
此解决方案的最大优点是简单,您不必处理约束和手势识别器.


Jac*_*art 2

您可以尝试将 UISwipeGestureRecognizer 添加到每个集合单元格,如下所示:

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
             cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CollectionViewCell *cell = ...

    UISwipeGestureRecognizer* gestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(userDidSwipe:)];
    [gestureRecognizer setDirection:UISwipeGestureRecognizerDirectionRight];
    [cell addGestureRecognizer:gestureRecognizer];
}
Run Code Online (Sandbox Code Playgroud)

其次是:

- (void)userDidSwipe:(UIGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
        //handle the gesture appropriately
    }
}
Run Code Online (Sandbox Code Playgroud)