我有一个3 x 3网格中有9个单元格的集合视图。我可以使用答案代码将单元格交换到这个问题 - Custom Cell Reorder Behavior in CollectionView,我也可以使用
旋转单元格如果让indexPath = self.collectionView?.indexPathForItem(at:sender.location(in:self.collectionView)){
let cell = self.collectionView?.cellForItem(at: indexPath)
cell?.transform = (cell?.transform.rotated(by: _direction))!
}
当我旋转一个单元格然后将其与另一个单元格交换时,会出现问题。旋转重置,单元格在交换后恢复到原始位置(0度)。
我希望能够旋转细胞然后交换它们而不会失去它们的旋转。
编辑: 这是我在View Controller中的旋转功能以及用于交换单元格的handleLongGesture函数:
@IBAction func userSwippedRight(_ sender: UISwipeGestureRecognizer) {
rotate(_direction: CGFloat(Double.pi / 2), sender: sender)
}
@IBAction func userSwippedLeft(_ sender: UISwipeGestureRecognizer) {
rotate(_direction: CGFloat(-Double.pi / 2), sender: sender)
}
func rotate(_direction: CGFloat, sender: UISwipeGestureRecognizer ) {
UIView.animate(withDuration: 0.25) {
if let indexPath = self.collectionView?.indexPathForItem(at: sender.location(in: self.collectionView)) {
let cell = self.collectionView?.cellForItem(at: indexPath)
cell?.transform = (cell?.transform.rotated(by: _direction))!
let radians:Float = atan2f(Float(cell!.transform.b), Float(cell!.transform.a))
var degrees:Int = Int(radians * Float(180 / Double.pi))
if(degrees == -180)
{
degrees = 180
}
print(degrees)
} else {
print("Swipe Registered")
}
}
}
func handleLongGesture(_ gesture: UILongPressGestureRecognizer) {
switch(gesture.state) {
case UIGestureRecognizerState.began:
guard let selectedIndexPath = self.collectionView?.indexPathForItem(at: gesture.location(in: self.collectionView)) else {
break
}
collectionView?.beginInteractiveMovementForItem(at: selectedIndexPath)
case UIGestureRecognizerState.changed:
collectionView?.updateInteractiveMovementTargetPosition(gesture.location(in: gesture.view!))
case UIGestureRecognizerState.ended:
collectionView?.endInteractiveMovement()
default:
collectionView?.cancelInteractiveMovement()
}
}
然后下面是UICollectionView的子类,我在其中为单元格的交互式移动添加了自定义处理。
import UIKit
extension UIView {
func snapshot() -> UIImage {
UIGraphicsBeginImageContext(self.bounds.size)
self.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
extension CGPoint {
func distanceToPoint(p:CGPoint) -> CGFloat {
return sqrt(pow((p.x - x), 2) + pow((p.y - y), 2))
}
}
struct SwapDescription : Hashable {
var firstItem : Int
var secondItem : Int
var hashValue: Int {
get {
return (firstItem * 10) + secondItem
}
}
}
func ==(lhs: SwapDescription, rhs: SwapDescription) -> Bool {
return lhs.firstItem == rhs.firstItem && lhs.secondItem == rhs.secondItem
}
class SwappingCollectionView: UICollectionView {
var interactiveCell = UICollectionViewCell()
var myView : UICollectionView?
var interactiveIndexPath : NSIndexPath?
var interactiveView : UIView?
var swapSet : Set<SwapDescription> = Set()
var previousPoint : CGPoint?
static let distanceDelta:CGFloat = 2 // adjust as needed
override func beginInteractiveMovementForItem(at indexPath: IndexPath) -> Bool {
self.interactiveIndexPath = indexPath as NSIndexPath?
self.interactiveCell = self.cellForItem(at: indexPath as IndexPath) as! CustomCellCollectionViewCell
self.interactiveCell.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
self.interactiveView = UIImageView(image: self.interactiveCell.snapshot())
self.interactiveView?.frame = self.interactiveCell.frame
self.addSubview(self.interactiveView!)
self.bringSubview(toFront: self.interactiveView!)
self.interactiveCell.isHidden = true
self.interactiveCell.transform = CGAffineTransform.identity
return true
}
override func updateInteractiveMovementTargetPosition(_ targetPosition: CGPoint) {
if (self.shouldSwap(newPoint: targetPosition)) {
if let hoverIndexPath = self.indexPathForItem(at: targetPosition), let interactiveIndexPath = self.interactiveIndexPath {
let swapDescription = SwapDescription(firstItem: interactiveIndexPath.item, secondItem: hoverIndexPath.item)
if (!self.swapSet.contains(swapDescription)) {
self.swapSet.insert(swapDescription)
self.performBatchUpdates({
self.moveItem(at: interactiveIndexPath as IndexPath, to: hoverIndexPath)
self.moveItem(at: hoverIndexPath, to: interactiveIndexPath as IndexPath)
}, completion: {(finished) in
self.swapSet.remove(swapDescription)
self.dataSource?.collectionView!(self, moveItemAt: interactiveIndexPath as IndexPath, to: hoverIndexPath as IndexPath)
self.interactiveIndexPath = hoverIndexPath as NSIndexPath?
})
}
}
}
self.interactiveView?.center = targetPosition
self.previousPoint = targetPosition
}
override func endInteractiveMovement() {
// Save the last rotation
self.cleanup()
}
override func cancelInteractiveMovement() {
self.cleanup()
}
func cleanup() {
self.interactiveCell.isHidden = false
self.interactiveView?.removeFromSuperview()
self.interactiveView = nil
self.interactiveCell.transform = CGAffineTransform.identity
self.interactiveIndexPath = nil
self.previousPoint = nil
self.swapSet.removeAll()
}
func shouldSwap(newPoint: CGPoint) -> Bool {
if let previousPoint = self.previousPoint {
let distance = previousPoint.distanceToPoint(p: newPoint)
return distance < SwappingCollectionView.distanceDelta
}
return false
}
}
我的collectionViewCell子类
import UIKit
import Firebase
import FirebaseDatabase
class CustomCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
}
答案 0 :(得分:1)
我建议不要操纵细胞的变换。我将设置UICollectionViewCell
的自定义子类,并将所有内容放在内容视图中并旋转。
我还会为每个自定义单元格赋予currentRotation
属性,并使其与变换的旋转同步。当您获取单元格或使单元格出列时,请检查它的currentRotation属性并使用它来查看是否需要旋转它。
答案 1 :(得分:0)
您应该将旋转状态存储在某处并将其应用于cellForItem(at:)
。为了获得进一步的帮助,我需要来自视图控制器的更多代码。