Je viens de commencer à me familiariser avec les UICollectionViews. Je me demande si quelqu'un sait comment spécifier le nombre de colonnes dans une collectionview. La valeur par défaut est de 3 (iPhone/portrait). J'ai consulté la documentation et je n'ai pas réussi à trouver une réponse concise.
Réponses
Trop de publicités?Cette réponse est pour swift 3.0 -->
se conformer d'abord au protocole :
UICollectionViewDelegateFlowLayout
puis ajoutez ces méthodes :
//this method is for the size of items
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width/3
let height : CGFloat = 160.0
return CGSize(width: width, height: height)
}
//these methods are to configure the spacing between items
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0,0,0,0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
Ajoutez d'abord UICollectionViewDelegateFlowLayout comme protocole.
Ensuite :
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
var columnCount = 3
let width = (view.frame.width - 20) / columnCount
return CGSize(width: width, height: width)
}
Tout dépend de la mise en page que vous souhaitez dessiner. Vous pouvez créer une classe personnalisée héritant de UICollectionViewFlowLayout. Actuellement, il n'existe pas de méthode directe pour définir les colonnes. Si vous souhaitez obtenir ce type de fonctionnalité, vous devez le faire manuellement. Vous devez le gérer dans votre classe de disposition de flux personnalisée.
La question qui se pose maintenant est de savoir comment vous allez vous y prendre. Si vous ne voulez pas perturber le cadre de la cellule vous pouvez ajuster
collectionView:layout:minimumInteritemSpacingForSectionAtIndex:
collectionView:layout:minimumLineSpacingForSectionAtIndex:
Une autre façon est de fournir vos propres positions de cellules. En surchargeant les deux méthodes ci-dessous, qui seront appelées pendant la formation de votre mise en page.
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path
UICollectionViewLayoutAttributes est une classe qui s'occupe de la position des cellules, du cadre, du Zindex, etc.
Je voulais juste compléter la réponse n°2 d'Imanou Petit. Pour garantir que les marges sont exactes quelle que soit la largeur de l'écran, j'utilise un solveur itératif avec une marge souhaitée et le nombre de colonnes comme entrées. J'ai également ajouté un drapeau directionnel sur l'endroit où les marges finales seront comparées à leur cible.
Le solveur itératif est présenté ci-dessous et renvoie cellWidth et margin.
private func iterativeCellSpacing(targetMargins : CGFloat,
cellsPerRow : Int,
isMinTarget : Bool) -> (CGFloat, CGFloat)
{
var w : CGFloat = 0
var m : CGFloat = targetMargins
let cols : CGFloat = CGFloat(cellsPerRow)
let numMargins : CGFloat = cols + 1.0
let screenWidth : CGFloat = collectionView!.bounds.size.width
var delta = CGFloat.greatestFiniteMagnitude
while abs(delta) > 0.001
{
let totalMarginSpacing = numMargins * m
let totalCellSpacing = screenWidth - totalMarginSpacing
if (isMinTarget)
{
w = floor(totalCellSpacing / cols)
m = ceil((screenWidth - cols * w) / numMargins)
}
else
{
w = ceil(totalCellSpacing / cols)
m = floor((screenWidth - cols * w) / numMargins)
}
delta = screenWidth - w * CGFloat(cellsPerRow) - m * numMargins
}
return (w, m)
}
Je l'appelle ainsi :
fileprivate var margin: CGFloat = 20
fileprivate var cellWidth : CGFloat = 80
fileprivate let cellsPerRow = 4
override func viewDidLoad()
{
super.viewDidLoad()
(cellWidth, margin) = iterativeCellSpacing(targetMargins: margin, cellsPerRow: 4, isMinTarget: true)
...
}
J'applique ensuite les valeurs de cellWidth et de marge à la mise en page du flux comme tel :
extension MyCollectionController : UICollectionViewDelegateFlowLayout
{ func collectionView(_ collectionView : UICollectionView, layout collectionViewLayout : UICollectionViewLayout, sizeForItemAt indexPath : IndexPath) -> CGSize { return CGSize(width : cellWidth, height : cellWidth) }
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
collectionView?.collectionViewLayout.invalidateLayout()
super.viewWillTransition(to: size, with: coordinator)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
return UIEdgeInsetsMake(margin, margin, margin, margin)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
{
return margin
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
{
return margin
}
}
J'espère que cela vous aidera. Il existe probablement un moyen plus simple de garantir l'exactitude des marges, mais il s'agit d'une méthode. De plus, ce code n'a pas été testé pour les appareils qui permettent la rotation des vues de collection.
Merci,
La solution idéale consiste à l'utilisation de UICollectionViewDelegateFlowLayout mais vous pouvez facilement calculer la largeur de la cellule et la diviser en fonction du nombre de colonnes que vous souhaitez.
l'astuce est de faire la largeur sans fraction.
(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat screenWidth = self.view.frame.size.width;
CGFloat marginWidth = (screenWidth - collectionView.frame.size.width);
CGFloat cellWith = (collectionView.frame.size.width - marginWidth )/3;
cellWith= floorf(cellWith);
CGSize retval = CGSizeMake(cellWith,cellWith);
return retval;}