113 votes

UICollectionView Définir le nombre de colonnes

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.

3voto

MhmdRizk Points 390

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
    }

3voto

Mahdi Moqadasi Points 121

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)
}

2voto

mobiSpace Points 863

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.

2voto

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,

0voto

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;}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X