Considérons un UICollectionView
avec disposition des flux et direction horizontale. Par défaut, les cellules sont ordonnées de haut en bas, de gauche à droite. Comme ceci :
1 4 7 10 13 16
2 5 8 11 14 17
3 6 9 12 15 18
Dans mon cas, la vue de la collection est paginée et elle a été conçue de manière à ce qu'un nombre spécifique de cellules tienne dans chaque page. Ainsi, un ordre plus naturel serait le suivant :
1 2 3 10 11 12
4 5 6 - 13 14 15
7 8 9 16 17 18
Quel serait le moyen le plus simple d'y parvenir, à moins d'implémenter ma propre mise en page personnalisée ? En particulier, je ne veux perdre aucune des fonctionnalités qui sont fournies gratuitement avec le logiciel UICollectionViewFlowLayout
(comme les animations d'insertion/suppression).
Ou en général, comment implémenter une fonction de réordonnancement f(n)
sur une disposition de flux ? La même chose pourrait s'appliquer à un ordre de droite à gauche, par exemple.
Mon approche jusqu'à présent
Ma première approche a été de sous-classer UICollectionViewFlowLayout
et de passer outre layoutAttributesForItemAtIndexPath:
:
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *reorderedIndexPath = [self reorderedIndexPathOfIndexPath:indexPath];
UICollectionViewLayoutAttributes *layout = [super layoutAttributesForItemAtIndexPath:reorderedIndexPath];
layout.indexPath = indexPath;
return layout;
}
Où reorderedIndexPathOfIndexPath:
es f(n)
. En appelant super
Je n'ai pas à calculer manuellement la disposition de chaque élément.
De plus, j'ai dû passer outre layoutAttributesForElementsInRect:
qui est la méthode utilisée par la mise en page pour choisir les éléments à afficher.
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *result = [NSMutableArray array];
NSInteger sectionCount = 1;
if ([self.collectionView.dataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)])
{
sectionCount = [self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView];
}
for (int s = 0; s < sectionCount; s++)
{
NSInteger itemCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:s];
for (int i = 0; i < itemCount; i++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:s];
UICollectionViewLayoutAttributes *layout = [self layoutAttributesForItemAtIndexPath:indexPath];
if (CGRectIntersectsRect(rect, layout.frame))
{
[result addObject:layout];
}
}
}
return result;
}
Ici, j'essaye juste chaque élément et s'il est dans la plage de tolérance donnée rect
je le renvoie.
Si cette approche est la bonne, j'ai les questions plus spécifiques suivantes :
- Y a-t-il un moyen de simplifier le
layoutAttributesForElementsInRect:
de passer outre, ou de le rendre plus efficace ? - Est-ce que je rate quelque chose ? Au minimum, l'échange de cellules de différentes pages produit des résultats étranges. Je pense que c'est lié à
initialLayoutAttributesForAppearingItemAtIndexPath:
yfinalLayoutAttributesForDisappearingItemAtIndexPath:
mais je n'arrive pas à déterminer exactement quel est le problème. - Dans mon cas,
f(n)
dépend du nombre de colonnes et de lignes de chaque page. Existe-t-il un moyen d'extraire cette information à partir deUICollectionViewFlowLayout
à moins de le coder moi-même en dur ? J'ai pensé à interrogation delayoutAttributesForElementsInRect:
avec les limites de la vue de la collection, et de déduire les lignes et les colonnes à partir de là, mais cela semble également inefficace.