Selon la documentation d'Apple (et vantée lors de la WWDC 2012), il est possible de définir la mise en page sur UICollectionView
de manière dynamique et même d'animer les changements :
Vous spécifiez normalement un objet de présentation lors de la création d'une vue de collection, mais vous pouvez également modifier la présentation d'une vue de collection de manière dynamique. L'objet de présentation est stocké dans la propriété collectionViewLayout. La définition de cette propriété permet de mettre à jour la présentation immédiatement, sans animer les modifications. Si vous souhaitez animer les modifications, vous devez appeler la méthode setCollectionViewLayout:animated :.
Toutefois, dans la pratique, j'ai constaté que UICollectionView
apporte des modifications inexplicables, voire non valables, à la contentOffset
Les cellules se déplacent alors de manière incorrecte, ce qui rend la fonction pratiquement inutilisable. Pour illustrer le problème, j'ai créé l'exemple de code suivant qui peut être attaché à un contrôleur de vue de collection par défaut placé dans un storyboard :
#import <UIKit/UIKit.h>
@interface MyCollectionViewController : UICollectionViewController
@end
@implementation MyCollectionViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"CELL"];
self.collectionView.collectionViewLayout = [[UICollectionViewFlowLayout alloc] init];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"contentOffset=(%f, %f)", self.collectionView.contentOffset.x, self.collectionView.contentOffset.y);
[self.collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init] animated:YES];
NSLog(@"contentOffset=(%f, %f)", self.collectionView.contentOffset.x, self.collectionView.contentOffset.y);
}
@end
Le contrôleur définit une valeur par défaut de UICollectionViewFlowLayout
en viewDidLoad
et affiche une seule cellule à l'écran. Lorsque la cellule est sélectionnée, le contrôleur crée une autre cellule par défaut. UICollectionViewFlowLayout
et la place dans la vue de la collection avec l'attribut animated:YES
drapeau. Le comportement attendu est que la cellule ne bouge pas. En réalité, la cellule défile hors de l'écran, et il n'est alors même plus possible de la faire revenir à l'écran.
En regardant le journal de la console, on s'aperçoit que le contentOffset a inexplicablement changé (dans mon projet, de (0, 0) à (0, 205)). J'ai publié une solution pour le solution pour le cas non animé ( i.e. animated:NO
), mais comme j'ai besoin d'animation, je suis très intéressé de savoir si quelqu'un a une solution ou une solution de contournement pour le cas de l'animation.
Par ailleurs, j'ai testé des mises en page personnalisées et j'obtiens le même résultat.
1 votes
ENFIN RÉSOLUE. @Isaacliu a donné la bonne réponse. J'ai mis la version moderne de Swift.
0 votes
setCollectionViewLayout(_:animated:)
a très bien fonctionné pour moi. Il suffit de faire quelque chose commecollectionView.setCollectionViewLayout(expanded ? self.verticalFlowLayout : self.horizontalFlowLayout, animated: true)