ios - El reordenamiento UICollectionViewController no funciona cuando está incrustado en una vista de contenedor
uicollectionview resize cell (2)
El problema aquí es que coloque el UICollectionView dentro de un UIContainerView que resida dentro de un UIViewController. Esto requiere solo unos pocos pasos más para que UICollectionView funcione como se espera.
Agregue lo siguiente a ViewDidLoad en su CollectionViewController:
self.collectionView!.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: "handleLongGesture:"))
A continuación, agregue la siguiente función a su CollectionViewController:
func handleLongGesture(gesture: UILongPressGestureRecognizer)
{
switch(gesture.state)
{
case UIGestureRecognizerState.Began:
guard let selectedIndexPath = self.collectionView!.indexPathForItemAtPoint(gesture.locationInView(self.collectionView)) else
{
break
}
collectionView!.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath)
case UIGestureRecognizerState.Changed:
collectionView!.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
case UIGestureRecognizerState.Ended:
collectionView!.endInteractiveMovement()
default:
collectionView!.cancelInteractiveMovement()
}
}
Finalmente, asegúrese de incluir lo siguiente para asegurarse de manejar el dataSource correctamente:
override func collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath,toIndexPath destinationIndexPath: NSIndexPath) {
// Swap the values of the source and destination
}
Consulte este enlace para obtener más información sobre esto.
Espero que esto te haya ayudado.
Reordenar funciona en iOS9 cuando agrego esto a mi subclase UICollectionViewController
override func collectionView(collectionView: UICollectionView,
moveItemAtIndexPath sourceIndexPath: NSIndexPath,
toIndexPath destinationIndexPath: NSIndexPath)
No funciona cuando esta subclase UICollectionViewController
está incrustada en una vista de contenedor.
He hecho una demostración del problema aquí
¿Alguna idea sobre por qué o cómo solucionarlo?
¡La respuesta de Scooter es correcta! Aquí está la versión de sintaxis de Swift 3:
import UIKit
class ViewController: UIViewController
{
// MARK: - IBOutlets
@IBOutlet weak var uiCollectionView: UICollectionView!
// MARK: - Lifecycle
override func viewDidLoad()
{
super.viewDidLoad()
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.handleLongGesture))
self.uiCollectionView.addGestureRecognizer(longPressGesture)
}
// MARK: - Gesture recogniser
@objc func handleLongGesture(gesture: UILongPressGestureRecognizer)
{
switch(gesture.state)
{
case .began:
guard let selectedIndexPath = self.uiCollectionView.indexPathForItem(at: gesture.location(in: self.uiCollectionView)) else
{
break
}
self.uiCollectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
case .changed:
self.uiCollectionView.updateInteractiveMovementTargetPosition(gesture.location(in: gesture.view!))
case .ended:
self.uiCollectionView.endInteractiveMovement()
default:
self.uiCollectionView.cancelInteractiveMovement()
}
}
}
// MARK: - UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
// TODO: Link to your data model
return 20
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
// TODO: Link to your data model
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView,
moveItemAt sourceIndexPath: IndexPath,
to destinationIndexPath: IndexPath)
{
// TODO: Update your data model to reflect the change
}
}
// MARK: - UICollectionViewDelegate
extension ViewController: UICollectionViewDelegate
{
// TODO: Add any UICollectionViewDelegate here if needed.
}
Tenga en cuenta que este código no tiene en cuenta el desplazamiento de la ubicación táctil, por lo que su celda ''saltará'' para centrarse debajo de su dedo mientras comienza a arrastrar. Si desea evitar eso, entonces deberá definir en su UIViewController
una propiedad CGPoint
(llamada initialGestureLocationInCell
en el código siguiente). Y luego sustituye en el ejemplo inicial con esto:
[...]
case .began:
guard let selectedIndexPath = self.uiCollectionView.indexPathForItem(at: gesture.location(in: self.uiCollectionView)) else
{
break
}
let selectedCell = self.uiCollectionView.cellForItem(at: selectedIndexPath)!
let gestureLocationInCell_RelativeToOrigin = gesture.location(in: selectedCell)
let gestureLocationInCell_RelativeToCentre = CGPoint(x: gestureLocationInCell_RelativeToOrigin.x - selectedCell.frame.size.width/2,
y: gestureLocationInCell_RelativeToOrigin.y - selectedCell.frame.size.height/2)
self.initialGestureLocationInCell = gestureLocationInCell_RelativeToCentre
self.uiCollectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
case .changed:
let gestureLocationInCollectionView = gesture.location(in: gesture.view!)
let targetPosition = CGPoint(x: gestureLocationInCollectionView.x - self.initialGestureLocationInCell.x,
y: gestureLocationInCollectionView.y - self.initialGestureLocationInCell.y)
self.uiCollectionView.updateInteractiveMovementTargetPosition(targetPosition)
[...]