24

UITableView のスワイプと同じ動作を UICollectionView で削除する方法を実装するにはどうすればよいでしょうか。チュートリアルを見つけようとしていますが、見つかりません。

また、iOS 5 をサポートするために PSTCollectionView ラッパーを使用しています。

ありがとうございました!

編集:スワイプ認識機能はすでに優れています。私が今必要としているのは、削除モードをキャンセルするときの UITableView と同じ機能です。たとえば、ユーザーがテーブル ビューのセルまたは空白スペースをタップしたとき (つまり、ユーザーが [削除] ボタンの外側をタップしたとき) です。UITapGestureRecognizer は、タッチのリリース時にタップを検出するだけなので、機能しません。UITableView は、ジェスチャの開始時に (リリース時ではなく) タッチを検出し、すぐに削除モードをキャンセルします。

4

7 に答える 7

14

とてもシンプルです..の後ろにcustomContentViewとを追加する必要があります。customBackgroundViewcustomContentView

その後、customContentViewユーザーが右から左にスワイプするときに、を左にシフトする必要があります。ビューをシフトすると、 が見えるようになりcustomBackgroundViewます。

レッツコード:

まず、panGesture を as に追加する必要がありますUICollectionView

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

    }

セレクターを次のように実装します

  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")
        }
    }

制約を更新するヘルパー メソッド

 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() }
        })
    }

ここでは Swift 3 でサンプル プロジェクトを作成しました。

これは、このチュートリアルの修正版です。

于 2016-11-07T12:49:15.187 に答える
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];
}

に続く:

- (void)userDidSwipe:(UIGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
        //handle the gesture appropriately
    }
}
于 2013-01-11T01:18:43.707 に答える