拖动时

时间:2016-10-18 19:15:53

标签: uicollectionview ios9 uicollectionviewcell

我能够通过使用手势识别器拖动它来重新排序iOS 9上的UICollectionViewCells,并简化新的iOS 9支持以进行重新排序。

public func beginInteractiveMovementForItemAtIndexPath(indexPath: NSIndexPath) -> Bool // returns NO if reordering was prevented from beginning - otherwise YES
public func updateInteractiveMovementTargetPosition(targetPosition: CGPoint)
public func endInteractiveMovement()
public func cancelInteractiveMovement()

我注意到当我开始拖动一个单元格时,它的中心变为触摸位置,我不喜欢这样。

如果我愿意的话,我希望能够通过它的角落拖动我的细胞。

你知道怎么做吗?

非常感谢。

2 个答案:

答案 0 :(得分:5)

(用Swift 3.1编写)

对于targetPosition函数的updateInteractiveMovementTargetPosition参数,而不是直接使用手势识别器的位置...

var location = recognizer.location(in: collectionView)            
collectionView.updateInteractiveMovementTargetPosition(location)

...我创建了一个函数,它将拖动单元​​格的中心(collectionView updateInteractiveMovementTargetPosition >使用的位置,然后获取手势识别器的位置& #39;触摸单元格中的 ,然后从单元格的中心减去它。

func offsetOfTouchFrom(recognizer: UIGestureRecognizer, inCell cell: UICollectionViewCell) -> CGPoint {

    let locationOfTouchInCell = recognizer.location(in: cell)

    let cellCenterX = cell.frame.width / 2
    let cellCenterY = cell.frame.height / 2

    let cellCenter = CGPoint(x: cellCenterX, y: cellCenterY)

    var offSetPoint = CGPoint.zero

    offSetPoint.y = cellCenter.y - locationOfTouchInCell.y
    offSetPoint.x = cellCenter.x - locationOfTouchInCell.x

    return offSetPoint

}

我的视图控制器中有一个简单的var offsetForCollectionViewCellBeingMoved: CGPoint = .zero,它将存储该偏移量,因此每次手势识别器的位置发生变化时,都不需要调用上面的函数。

所以我的手势识别器的目标看起来像这样:

func collectionViewLongPressGestureRecognizerWasTriggered(recognizer: UILongPressGestureRecognizer) {

    guard let indexPath = collectionView.indexPathForItem(at: recognizer.location(in: self.collectionView)),
        let cell = collectionView.cellForItem(at: indexPath), indexPath.item != 0 else { return }

    switch recognizer.state {

    case .began:

        collectionView.beginInteractiveMovementForItem(at: indexPath)

        // This is the class variable I mentioned above
        offsetForCollectionViewCellBeingMoved = offsetOfTouchFrom(recognizer: recognizer, inCell: cell)

        // This is the vanilla location of the touch that alone would make the cell's center snap to your touch location
        var location = recognizer.location(in: collectionView)

        /* These two lines add the offset calculated a couple lines up to 
        the normal location to make it so you can drag from any part of the 
        cell and have it stay where your finger is. */

        location.x += offsetForCollectionViewCellBeingMoved.x
        location.y += offsetForCollectionViewCellBeingMoved.y

        collectionView.updateInteractiveMovementTargetPosition(location)

    case .changed:

        var location = recognizer.location(in: collectionView)

        location.x += offsetForCollectionViewCellBeingMoved.x
        location.y += offsetForCollectionViewCellBeingMoved.y

        collectionView.updateInteractiveMovementTargetPosition(location)

    case .ended:
        collectionView.endInteractiveMovement()

    default:
        collectionView.cancelInteractiveMovement()
    }
}

答案 1 :(得分:3)

如果您的集合视图仅向一次方向滚动,那么实现此目的的最简单方法是简单地锁定不滚动到硬编码的轴,这意味着您的单元格将仅在您可以滚动的轴上移动。以下是代码,请参阅已更改案例......

@objc func handleLongGesture(gesture: UILongPressGestureRecognizer) {
    switch gesture.state {
    case .began:
        guard let selectedIndexPath = self.collectionView
            .indexPathForItem(at: gesture
                .location(in: self.collectionView)) else { break }
        collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
    case .changed:
        var gesturePosition = gesture.location(in: gesture.view!)
        gesturePosition.x = (self.collectionView.frame.width / 2) - 20
        collectionView.updateInteractiveMovementTargetPosition(gesturePosition)
    case .ended:
        collectionView.endInteractiveMovement()
    default:
        collectionView.cancelInteractiveMovement()
    }
}