77 votes

Swift : Comment rafraîchir la mise en page d'UICollectionView après une rotation du dispositif ?

J'ai utilisé UICollectionView (flowlayout) pour construire une mise en page simple. la largeur de chaque cellule est fixée à la largeur de l'écran en utilisant self.view.frame.width

mais lorsque je fais pivoter l'appareil, les cellules ne sont pas mises à jour.

enter image description here

J'ai trouvé une fonction, qui est appelée lors du changement d'orientation :

override func willRotateToInterfaceOrientation(toInterfaceOrientation: 
  UIInterfaceOrientation, duration: NSTimeInterval) {
    //code
}

mais je n'arrive pas à trouver un moyen de mettre à jour la disposition de UICollectionView

Le code principal est ici :

class ViewController: UIViewController , UICollectionViewDelegate , UICollectionViewDataSource , UICollectionViewDelegateFlowLayout{

    @IBOutlet weak var myCollection: UICollectionView!

    var numOfItemsInSecOne: Int!
    override func viewDidLoad() {
        super.viewDidLoad()

        numOfItemsInSecOne = 8
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {

        //print("orientation Changed")
    }

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return numOfItemsInSecOne
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cellO", forIndexPath: indexPath)

        return cell
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{
    let itemSize = CGSize(width: self.view.frame.width, height: 100)
    return itemSize
    }}

79voto

Khuong Points 4807

Ajoutez cette fonction :

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews() 
    myCollection.collectionViewLayout.invalidateLayout()
}

Lorsque vous changez l'orientation, cette fonction est appelée.

0 votes

Merci @khuong291 que se passe-t-il si je n'ai pas d'objet de ma collectionview, et que j'ai UICollectionViewController ? comment vais-je faire pour appeler reloadData ?

2 votes

UICollectionViewController a déjà collectionView donc il suffit de les appeler comme je l'ai dit. Il suffit de les éditer dans collectionView.reloadData() . Il fonctionnera.

2 votes

Vous devez donc recharger la vue, vous ne pouvez pas simplement déclencher un rafraîchissement de la mise en page ?

63voto

kelin Points 5278

La meilleure option est d'appeler invalidateLayout() au lieu de reloadData() car il ne forcera pas la recréation des cellules, les performances seront donc légèrement meilleures :

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews() 
    myCollection.collectionViewLayout.invalidateLayout()
}

0 votes

C'est la bonne façon de faire. Ceci devrait être la réponse acceptée.

0 votes

C'est la façon correcte de le faire pas le rechargement des données à nouveau

9 votes

Cela a provoqué un écrasement pour moi. et une boucle infinie reconnue lorsque j'ai mis une instruction print dans la fonction viewDidLayoutSubviews.

17voto

awuu Points 129

Vous pouvez également l'invalider de cette manière.

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    [self.collectionView.collectionViewLayout invalidateLayout]; 
}

16voto

The Doctor Points 123

La fonction viewWillLayoutSubviews() n'a pas fonctionné pour moi. Tout comme viewDidLayoutSubviews(). Les deux font entrer l'application dans une boucle infinie que j'ai vérifiée en utilisant une commande print.

L'une des façons de faire est

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
// Reload here
}

16 votes

N'oubliez pas d'appeler super.viewWillTransition...

3voto

Abhinandan Pratap Points 1069

Vous pouvez mettre à jour votre UICollectionView Layout en utilisant

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    if isLandscape {
        return CGSizeMake(yourLandscapeWidth, yourLandscapeHeight)
    }
    else {
        return CGSizeMake(yourNonLandscapeWidth, yourNonLandscapeHeight)
    }
}

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