J'essaie actuellement d'implémenter le comportement de réorganisation UITableView en utilisant UICollectionView.
Appelons un ItableView TV et un ICollectionView CV (pour clarifier l'explication suivante)
J'essaie essentiellement de reproduire le glisser-déposer du téléviseur, mais je n'utilise pas le mode d'édition, la cellule est prête à être déplacée dès que le geste de pression longue est déclenché. Cela fonctionne parfaitement, j'utilise la méthode de déplacement du CV, tout va bien.
Je mets à jour la propriété contentOffset du CV pour gérer le défilement lorsque l'utilisateur fait glisser une cellule. Lorsqu'un utilisateur se rend dans un rect en particulier en haut et en bas, je mets à jour le contentOffset et le défilement du CV. Le problème est que lorsque l'utilisateur arrête de bouger son doigt, le geste n'envoie aucune mise à jour qui arrête le défilement et recommence dès que l'utilisateur déplace son doigt.
Ce comportement n'est certainement pas naturel, je préférerais continuer à faire défiler jusqu'à ce que l'utilisateur relâche le CV comme c'est le cas sur le téléviseur. L'expérience TV glisser-déposer est géniale et je veux vraiment reproduire le même sentiment. Est-ce que quelqu'un sait comment il gère le défilement de la télévision pendant la réorganisation?
J'ai manqué d'idée à ce sujet, donc si quelqu'un a la réponse, je l'épouserais!
Voici l'implémentation de la méthode longPress:
- (void)handleLongPress:(UILongPressGestureRecognizer *)sender
{
ReorganizableCVCLayout *layout = (ReorganizableCVCLayout *)self.collectionView.collectionViewLayout;
CGPoint gesturePosition = [sender locationInView:self.collectionView];
NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:gesturePosition];
if (sender.state == UIGestureRecognizerStateBegan)
{
layout.selectedItem = selectedIndexPath;
layout.gesturePoint = gesturePosition; // Setting gesturePoint invalidate layout
}
else if (sender.state == UIGestureRecognizerStateChanged)
{
layout.gesturePoint = gesturePosition; // Setting gesturePoint invalidate layout
[self swapCellAtPoint:gesturePosition];
[self manageScrollWithReferencePoint:gesturePosition];
}
else
{
[self.collectionView performBatchUpdates:^
{
layout.selectedItem = nil;
layout.gesturePoint = CGPointZero; // Setting gesturePoint invalidate layout
} completion:^(BOOL completion){[self.collectionView reloadData];}];
}
}
Pour faire défiler le CV, j'utilise cette méthode:
- (void)manageScrollWithReferencePoint:(CGPoint)gesturePoint
{
ReorganizableCVCLayout *layout = (ReorganizableCVCLayout *)self.collectionView.collectionViewLayout;
CGFloat topScrollLimit = self.collectionView.contentOffset.y+layout.itemSize.height/2+SCROLL_BORDER;
CGFloat bottomScrollLimit = self.collectionView.contentOffset.y+self.collectionView.frame.size.height-layout.itemSize.height/2-SCROLL_BORDER;
CGPoint contentOffset = self.collectionView.contentOffset;
if (gesturePoint.y < topScrollLimit && gesturePoint.y - layout.itemSize.height/2 - SCROLL_BORDER > 0)
contentOffset.y -= SCROLL_STEP;
else if (gesturePoint.y > bottomScrollLimit &&
gesturePoint.y + layout.itemSize.height/2 + SCROLL_BORDER < self.collectionView.contentSize.height)
contentOffset.y += SCROLL_STEP;
[self.collectionView setContentOffset:contentOffset];
}
Cela pourrait aider
https://github.com/lxcid/LXReorderableCollectionViewFlowLayout
Ceci étend le UICollectionView
pour permettre à chacun des UICollectionViewCells
d'être réarrangé manuellement par l'utilisateur avec une longue touche (alias toucher et maintenir). L'utilisateur peut faire glisser la cellule vers n'importe quelle autre position de la collection et les autres cellules se réorganiseront automatiquement. Merci d'aller à lxcid pour cela.
Ici est une alternative:
Les différences entre DraggableCollectionView et LXReorderableCollectionViewFlowLayout sont:
CADisplayLink
pour un défilement et une animation fluides.UICollectionViewDataSource
avec des méthodes similaires à UITableViewDataSource
.C'est un travail en cours. Plusieurs sections sont désormais prises en charge.
Pour l'utiliser avec une mise en page personnalisée, voir DraggableCollectionViewFlowLayout
. La plupart de la logique existe dans LSCollectionViewLayoutHelper
. Il y a aussi un exemple dans CircleLayoutDemo montrant comment faire fonctionner l'exemple CircleLayout d'Apple à partir de la WWDC 2012.
Depuis iOS 9, UICollectionView
prend désormais en charge la réorganisation.
Pour UICollectionViewController
s, remplacez simplement collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
Pour UICollectionView
s, vous devrez gérer les gestes vous-même en plus d'implémenter la méthode UICollectionViewDataSource
ci-dessus.
Voici le code de la source:
private var longPressGesture: UILongPressGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
longPressGesture = UILongPressGestureRecognizer(target: self, action: "handleLongGesture:")
self.collectionView.addGestureRecognizer(longPressGesture)
}
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()
}
}
http://nshint.io/blog/2015/07/16/uicollectionviews-now-have-easy-reordering/
Si vous voulez expérimenter le déploiement du vôtre, je viens d'écrire un tutoriel basé sur Swift que vous pouvez consulter. J'ai essayé de construire le plus basique des cas afin d'être plus facile à suivre ceci .
Ici est une autre approche:
La principale différence est que cette solution ne nécessite pas de cellule "fantôme" ou "factice" pour fournir la fonctionnalité de glisser-déposer. Il utilise simplement la cellule elle-même. Les animations sont conformes à UITableView. Il fonctionne en ajustant la source de données privée de la présentation de la vue de la collection tout en vous déplaçant. Une fois que vous lâchez prise, il indiquera à votre contrôleur que vous pouvez valider la modification dans votre propre source de données.
Je pense qu'il est un peu plus simple de travailler avec la plupart des cas d'utilisation. Encore un travail en cours, mais encore une autre façon d'y parvenir. La plupart devraient trouver cela assez facile à intégrer dans leur propre UICollectionViewLayouts personnalisé.