J'ai un UIScrollView
qui présente une grille d'icônes. Si vous deviez imaginer la mise en page pour le Springboard iOS, vous seriez assez près pour corriger. Il a un défilement horizontal, paginé (tout comme Springboard). Cependant, il semble que la disposition ne soit pas tout à fait correcte. Il semble que les éléments soient disposés de haut en bas. En conséquence, ma dernière colonne ne contient que 2 lignes, en raison du nombre d'éléments à afficher. Je préférerais que ma dernière ligne de la dernière page contienne 2 éléments, comme vous le verriez dans le Tremplin.
Comment cela peut-il être accompli avec UICollectionView
et ses classes associées? Dois-je écrire un UICollectionViewFlowLayout
personnalisé?
Qu'en est-il de l'utilisation de UIPageViewController
avec un tableau de UICollectionViewControllers
? Vous devrez chercher le nombre approprié d'éléments dans chaque UICollectionViewController
, mais cela ne devrait pas être difficile. Vous obtiendrez exactement le même look que le Springboard.
J'ai réfléchi à cela et à mon avis, vous devez définir:
self.collectionView.pagingEnabled = YES;
et créez votre propre présentation de vue de collection en sous-classant UICollectionViewLayout
. À partir de l'objet de présentation personnalisé, vous pouvez accéder à self.collectionView
, vous saurez ainsi quelle est la taille de la frame
, numberOfSections
et numberOfItemsInSection:
. Avec cette information, vous pouvez calculer les cellules frames
(dans prepareLayout
) et collectionViewContentSize
. Voici quelques articles sur la création de mises en page personnalisées:
Vous pouvez faire ceci (ou une approximation de celui-ci) sans créer la disposition personnalisée. Ajoutez UIScrollView
dans la vue vide, activez la pagination. Dans la vue de défilement, ajoutez la vue de collection. Ajoutez-y ensuite une contrainte de largeur, vérifiez dans le code le nombre d’éléments que vous possédez et affectez à constant
la valeur correcte, par exemple. (self.view.frame.size.width * numOfScreens)
. Voici à quoi cela ressemble (les chiffres sur les cellules indiquent le indexPath.row
): https://www.dropbox.com/s/ss4jdbvr511azxz/collection_view.mov Si vous n'êtes pas satisfait de la façon dont les cellules sont commandées, je crains fort que ce ne soit le cas aller avec 1. ou 2.
Avez-vous essayé de définir le sens de défilement de votre UICollectionViewFlowLayout sur horizontal?
[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
Et si vous souhaitez que la page se comporte comme le springboard, vous devez activer la pagination sur la vue de votre collection de la manière suivante:
[yourCollectionView setPagingEnabled:YES];
Vous devez réduire la hauteur de UICollectionView
à sa hauteur de cellule/d’élément et sélectionner "Horizontal
" dans la liste "Scroll Direction
"comme dans la capture d'écran ci-dessous. Ensuite, il défilera horizontalement en fonction du numberOfItems
que vous avez renvoyé dans son implémentation de source de données.
Si vous définissez UICollectionViewFlowLayout
dans le code, cela annulera les configurations d'Interface Builder. Par conséquent, vous devez redéfinir le scrollDirection
.
let layout = UICollectionViewFlowLayout()
...
layout.scrollDirection = .Horizontal
self.awesomeCollectionView.collectionViewLayout = layout
Juste pour le plaisir, une autre approche serait de simplement laisser le jeu de pagination et de défilement horizontal, d’ajouter une méthode qui change l’ordre des éléments du tableau à convertir de 'haut en bas, de gauche à droite' en visuellement 'De gauche à droite, de haut en bas' et remplissez les cellules intermédiaires avec des cellules cachées vides pour que l'espacement soit correct. Dans le cas de 7 éléments dans une grille de 9, ceci ressemblerait à ceci:
[1][4][7]
[2][5][ ]
[3][6][ ]
devraient devenir
[1][2][3]
[4][5][6]
[7][ ][ ]
donc 1 = 1, 2 = 4, 3 = 7 etc. et 6 = vide. Vous pouvez les réorganiser en calculant le nombre total de lignes et de colonnes, puis calculer le numéro de ligne et de colonne pour chaque cellule, modifier la ligne de la colonne, et inversement, pour obtenir les nouveaux index. Lorsque la cellule n'a pas de valeur correspondant à l'image, vous pouvez retourner une cellule vide et définir cell.hidden = YES;
à elle.
Cela fonctionne très bien dans une application de table de son que j'ai construite, donc si quelqu'un veut du code fonctionnel, je l'ajouterai. Il ne faut que peu de code pour que cette astuce fonctionne, ça sonne plus fort que ça!
Mise à jour
Je doute que ce soit la meilleure solution, mais à la demande, voici le code de travail:
- (void)viewDidLoad {
// Fill an `NSArray` with items in normal order
items = [NSMutableArray arrayWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 1", @"label", @"Some value 1", @"value", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 2", @"label", @"Some value 2", @"value", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 3", @"label", @"Some value 3", @"value", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 4", @"label", @"Some value 4", @"value", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 5", @"label", @"Some value 5", @"value", nil],
nil
];
// Calculate number of rows and columns based on width and height of the `UICollectionView` and individual cells (you might have to add margins to the equation based on your setup!)
CGFloat w = myCollectionView.frame.size.width;
CGFloat h = myCollectionView.frame.size.height;
rows = floor(h / cellHeight);
columns = floor(w / cellWidth);
}
// Calculate number of sections
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return ceil((float)items.count / (float)(rows * columns));
}
// Every section has to have every cell filled, as we need to add empty cells as well to correct the spacing
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return rows*columns;
}
// And now the most important one
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier@"myIdentifier" forIndexPath:indexPath];
// Convert rows and columns
int row = indexPath.row % rows;
int col = floor(indexPath.row / rows);
// Calculate the new index in the `NSArray`
int newIndex = ((int)indexPath.section * rows * columns) + col + row * columns;
// If the newIndex is within the range of the items array we show the cell, if not we hide it
if(newIndex < items.count) {
NSDictionary *item = [items objectAtIndex:newIndex];
cell.label.text = [item objectForKey:@"label"];
cell.hidden = NO;
} else {
cell.hidden = YES;
}
return cell;
}
Si vous souhaitez utiliser la méthode didSelectItemAtIndexPath
, vous devez utiliser la même conversion que celle utilisée dans cellForItemAtIndexPath
pour obtenir l'élément correspondant. Si vous avez des marges de cellule, vous devez les ajouter au calcul des lignes et des colonnes, car elles doivent être correctes pour que cela fonctionne.
Ce code fonctionne bien dans Swift 3.1 et Xcode 8.3.2
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
self.collectionView.collectionViewLayout = layout
self.collectionView!.contentInset = UIEdgeInsets(top: -10, left: 0, bottom:0, right: 0)
if let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.itemSize = CGSize(width: self.view.frame.size.width-40, height: self.collectionView.frame.size.height-10)
layout.invalidateLayout()
}
}
De @Erik Hunter, je poste le code complet pour make horizontal UICollectionView
UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[collectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
self.myCollectionView.collectionViewLayout = collectionViewFlowLayout;
En rapide
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .Horizontal
self.myCollectionView.collectionViewLayout = layout
Dans Swift 3.0
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
self.myCollectionView.collectionViewLayout = layout
J'espère que cette aide
Je travaille sur Xcode 6.2 et pour le défilement horizontal, j’ai changé le sens du défilement dans l’inspecteur d’attributs.
cliquez sur collectionView-> attribut attribut-> défilement Direction-> changer à l'horizontale
J'espère que ça aide quelqu'un.
Nous pouvons utiliser le même comportement Springboard avec UICollectionView et pour cela, nous devons écrire du code pour une présentation personnalisée.
Je l'ai atteint avec mon implémentation de classe de présentation personnalisée avec "SMCollectionViewFillLayout"
Dépôt de code:
https://github.com/smindia1988/SMCollectionViewFillLayout
Sortie comme ci-dessous:
1.png
2_Code_H-Scroll_V-Fill.png
Vous pouvez écrire une mise en page personnalisée UICollectionView
pour y parvenir, voici une image démo de mon implémentation:
Voici le référentiel de code: KSTCollectionViewPageHorizontalLayout
@iPhoneDev (cela peut peut-être vous aider aussi)