简体   繁体   English

iOS-水平滑动UICollectionViewCell

[英]iOS - swipe UICollectionViewCell horizontally

I have a UICollectionView that looks like a tableView and I want the cells to swipe only horizontally. 我有一个看起来像tableView的UICollectionView,我希望单元格只能水平滑动。

I have managed to make them to move around, but the problem is I can move them up as well and basically I can move them in any direction and I want them to swipe like a tableViewCell when you delete it for example. 我设法使它们移动,但是问题是我也可以将它们向上移动,并且基本上可以沿任何方向移动它们,例如,当您删除它时,我希望它们像tableViewCell一样滑动。

In the end I want to be able to just swipe a cell out of the screen horizontally 最后,我希望能够水平滑动屏幕上的某个单元格

I have attached a image of how the collection view looks now and a cell that moves around(the red one) 我已附上一张图像,该图像显示了收集视图现在的外观以及一个移动的单元格(红色的)

在此处输入图片说明

I found a way to do it with UIPanGestureRecognizer after all. 毕竟,我找到了一种使用UIPanGestureRecognizer进行操作的方法。 All the operations are on the cell(inside the cell class). 所有操作都在单元格上(单元格类内部)。 Below you have the solution that worked for me 下面是对我有用的解决方案

var swipeGesture: UIPanGestureRecognizer!
var originalPoint: CGPoint!

func configureCell() {
    setupSwipeGesture()
}

func setupSwipeGesture() {
        swipeGesture = UIPanGestureRecognizer(target: self, action:#selector(swiped(_:)))
        swipeGesture.delegate = self

        self.addGestureRecognizer(swipeGesture)
    }


func swiped(_ gestureRecognizer: UIPanGestureRecognizer) {
let xDistance:CGFloat = gestureRecognizer.translation(in: self).x

        switch(gestureRecognizer.state) {
        case UIGestureRecognizerState.began:
            self.originalPoint = self.center
        case UIGestureRecognizerState.changed:
            let translation: CGPoint = gestureRecognizer.translation(in: self)
            let displacement: CGPoint = CGPoint.init(x: translation.x, y: translation.y)

            if displacement.x + self.originalPoint.x < self.originalPoint.x {
                self.transform = CGAffineTransform.init(translationX: displacement.x, y: 0)
                self.center = CGPoint(x: self.originalPoint.x + xDistance, y: self.originalPoint.y)
            }
        case UIGestureRecognizerState.ended:
            let hasMovedToFarLeft = self.frame.maxX < UIScreen.main.bounds.width / 2
            if (hasMovedToFarLeft) {
                removeViewFromParentWithAnimation()
            } else {
                resetViewPositionAndTransformations()
            }
        default:
            break
        }
    }

func resetViewPositionAndTransformations(){
        UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(), animations: {
            self.center = self.originalPoint
            self.transform = CGAffineTransform(rotationAngle: 0)
        }, completion: {success in })
    }

func removeViewFromParentWithAnimation() {
        var animations:(()->Void)!
        animations = {self.center.x = -self.frame.width}

        UIView.animate(withDuration: 0.2, animations: animations , completion: {success in self.removeFromSuperview()})
    }

You will need to do a few things: 您将需要做一些事情:

1) Add a UISwipeGestureRecognizer to each cell. 1)向每个单元格添加一个UISwipeGestureRecognizer Be sure to set direction = .left . 确保将direction = .left设置direction = .left

2) Add the target for the gesture recognizer, and make sure the target can communicate with the collection view's layout. 2)为手势识别器添加目标,并确保目标可以与集合视图的布局通信。 2a) The collection view data source could add the target in cellForItemAtIndexPath . 2a)集合视图数据源可以将目标添加到cellForItemAtIndexPath You would need a way to make sure it's not added repeatedly on reused cells. 您需要一种方法来确保它不会在重复使用的单元格上重复添加。 2b) You could add the gesture recognizer from within the cell, and create a delegate relationship with your view controller. 2b)您可以在单元格中添加手势识别器,并与视图控制器创建委托关系。

3) You will need the index path of the cell that was swiped. 3)您将需要被刷过的单元格的索引路径。 To get the cell from the gesture recognizer (2a) call it's view property and cast as UICollectionViewCell. 要从手势识别器(2a)中获取单元格,请调用其view属性并转换为UICollectionViewCell。 If you use a delegate (2b) or another method, it should pass the cell back. 如果使用委托(2b)或其他方法,则应将单元格传回。 Then you can call collectionView.cellForItem(at indexPath: IndexPath) -> UICollectionViewCell? 然后,您可以调用collectionView.cellForItem(at indexPath: IndexPath) -> UICollectionViewCell? to get the index path. 获取索引路径。

4) Call deleteItemAtIndexPath: on the collection view, in performBatchUpdates etc. 4)在集合视图, performBatchUpdates等中调用deleteItemAtIndexPath:

5) It seems the simplist way to animate the disappearance to the left (disclaimer, I haven't done this part myself though I've worked with attributes) is to implement finalLayoutAttributesForDisappearingItemAtIndexPath: in a subclass of UICollectionViewLayout. 5)似乎可以用动画的方式简化左边的消失(免责声明,尽管我已经使用过属性,但我自己还没有完成这部分工作)是在UICollectionViewLayout的子类中实现finalLayoutAttributesForDisappearingItemAtIndexPath :。

First, you will need the attributes cached. 首先,您需要缓存属性。 So override and cache: 因此,覆盖并缓存:

class LeftDisappearLayout : UICollectionViewFLowLayout {

    var cachedAttributes = [NSIndexPath:UICollectionViewAttributes?]()

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attributes = super.layoutAttributesForItem(at: indexPath) 
        cachedAttributes[indexPath] = attributes
        return attributes
    }

Then since iOS 9 it appears there's a simple way to have the system animate to the left for you: 然后从iOS 9开始,出现了一种简单的方法让系统为您创建左侧动画:

    func finalLayoutAttributesForDisappearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        if var attributes = cachedAttributes[indexPath] {
            let newCenterX : CGFloat = -1 * (attributes.frame.size.width / 2)  
            attributes.center = CGPoint(newCenterX, attributes.center.y)
            return attributes 
        }
        AssertionFailure("Unable to find cached attributes!") // Saying, "This should never happen and in development crash to alert the developer, but in production gracefully revert to default."
        return nil
    }
}

Make sure to set your collection view to use this layout. 确保将您的收藏夹视图设置为使用此布局。 Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM