2015-12-07 12 views
29

Ich habe eine UICollectionView erstellt, so dass ich Ansichten in ordentliche Spalten arrangieren kann. Ich möchte, dass eine einzelne Spalte auf Geräten mit einer Breite von> 500 Pixel angezeigt wird.UICollectionView - Ändern der Größe von Zellen auf dem Gerät drehen - Swift

Um dies zu erreichen, habe ich diese Funktion:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { 
    let size = collectionView.frame.width 
    if (size > 500) { 
     return CGSize(width: (size/2) - 8, height: (size/2) - 8) 
    } 
    return CGSize(width: size, height: size) 
} 

Dies als beim ersten Laden erwartet funktioniert, aber wenn ich das Gerät drehen, die Berechnung nicht immer wieder passieren, und die Ansichten don Zeichne immer wie erwartet neu. Hier ist mein Code für, wenn das Gerät gedreht wird:

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) { 
    collectionView.collectionViewLayout.invalidateLayout() 
    self.view.setNeedsDisplay() 
} 

Ich gehe davon aus ich habe vergessen, etwas neu zu zeichnen, aber ich bin nicht sicher, was. Irgendwelche Ideen werden sehr dankbar empfangen!

Antwort

18

Sie könnten viewWillLayoutSubviews verwenden. This question sollte hilfreich sein, aber dies wird bassisch aufgerufen, wenn die View-Controller-Ansichten im Begriff sind, seine Subviews zu gestalten.

So wird Ihr Code wie folgt aussehen:

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 

    guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { 
    return 
    } 

    if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) { 
    //here you can do the logic for the cell size if phone is in landscape 
    } else { 
    //logic if not landscape 
    } 

    flowLayout.invalidateLayout() 
} 
+6

von diesem Ansatz werden Sie eine Endlosschleife eingeben. – valvoline

+3

Ich bin nicht sicher, dass @valvoline korrekt ist, dass dies eine Endlosschleife verursacht - aber es kann durchaus zu Leistungsproblemen kommen, da es das Sammlungsansichtslayout viel öfter als notwendig ungültig macht. Es ist viel besser, 'viewWillTransitionToSize' zu ​​verwenden. – JosephH

+3

Dieser Code verursacht eine Endlosschleife. Es sollte nicht die richtige Antwort sein. – Josh

13

ich neigten habe viewWillTransitionToSize mit der gleichen Sache zu verwenden, und machte einfach einen Anruf invalidateLayout() drin.

22

Vielleicht ist der direkteste Weg, dies zu machen, ist zu invalidateLayout während des viewWillTransitionToSize:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    super.viewWillTransition(to: size, with: coordinator) 
    guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { 
     return 
    } 
    flowLayout.invalidateLayout() 
} 
0

ich eine Aufgabe hatte Artikel Größe in UICollectionView Unterklasse anzupassen. Die beste Methode hierfür ist setFrame. Property collectionViewFlowLayout Ich habe von ViewController übergeben (in meinem Fall war es outlet von Standard-Flow-Layout).

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 
    super.traitCollectionDidChange(previousTraitCollection) 

    guard let previousTraitCollection = previousTraitCollection, traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass || 
     traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass else { 
      return 
    } 

    if traitCollection.horizontalSizeClass == .regular && traitCollection.verticalSizeClass == .regular { 
     // iPad portrait and landscape 
     // do something here... 
    } 
    if traitCollection.horizontalSizeClass == .compact && traitCollection.verticalSizeClass == .regular { 
     // iPhone portrait 
     // do something here... 
    } 
    if traitCollection.horizontalSizeClass == .regular && traitCollection.verticalSizeClass = .compact { 
     // iPhone landscape 
     // do something here... 
    } 
    collectionView?.collectionViewLayout.invalidateLayout() 
    collectionView?.reloadData() 
} 
0

traitCollectionDidChange Methode könnte auch statt viewWillLayoutSubviews verwendet werden. Nachdem die Querformat-/Porträtanimation beendet ist, müssen Sie sie so schnell wie möglich entfernen. Hier

ein Beispiel:

@property (strong, nonatomic) UIImageView *maskImage; 

......... 

- (UIImageView *) imageForCellAtIndex: (NSInteger) index { 
    UICollectionView *collectionView = self.pagerView.test; 
    FSPagerViewCell *cell = nil; 
    NSArray *indexPaths = [collectionView indexPathsForVisibleItems]; 
    for (NSIndexPath *indexPath in indexPaths) { 
     if (indexPath.item == index) { 
      cell = (FSPagerViewCell *)[collectionView cellForItemAtIndexPath: indexPath]; 
      break; 
     } 
    } 
    if (cell) { 
     return cell.imageView; 
    } 
    return nil; 
} 


- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator 

{ 
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; 

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) 
    { 
     UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 
     [self test_didRotateFromInterfaceOrientation: orientation]; 

     UIImageView *imageView = [self imageForCellAtIndex: self.pagerView.currentIndex]; 
     if (imageView) { 
       UIImageView *imageView = [self imageForCellAtIndex: self.pagerView.currentIndex]; 
       CGSize itemSize = self.pagerView.itemSize; 
       UIImageView *newImage = [[UIImageView alloc] initWithImage: imageView.image]; 
       [newImage setFrame: CGRectMake((_contentView.bounds.size.width - itemSize.width)/2.0f, 0, itemSize.width, itemSize.height)]; 
       newImage.contentMode = imageView.contentMode; 
       newImage.clipsToBounds = imageView.clipsToBounds; 
       newImage.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 
       [self.pagerView addSubview: newImage]; 

       self.maskImage = newImage; 
     } 

     [self.pagerView.test performBatchUpdates:^{ 
      [self.pagerView.test setCollectionViewLayout:self.pagerView.test.collectionViewLayout animated:YES]; 
     } completion:nil]; 
     // do whatever 
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) 
    { 
     [self.maskImage removeFromSuperview]; 
    }]; 
} 
0

Sie können eine Maske Inhalte erstellen und an die Kollektion bewegen:

// .h 
@property (nonatomic, weak) UICollectionViewFlowLayout *collectionViewFlowLayout; 

// .m 
- (void)setFrame:(CGRect)frame { 
    if (!CGSizeEqualToSize(frame.size, self.frame.size)) { 
     collectionViewFlowLayout.itemSize = 
     CGSizeMake((UIDeviceOrientationIsLandscape(UIDevice.currentDevice.orientation) ? (frame.size.width - 10)/2 : frame.size.width), collectionViewFlowLayout.itemSize.height); 
    } 
    [super setFrame:frame]; 
} 
Verwandte Themen