ios Come definisco la dimensione di un CollectionView su Ruota




objective-c xcode (6)

Ho risolto questo problema controllando la rotazione del dispositivo e ricaricando il layout. Controllo delle dimensioni dello schermo e utilizzo di queste dimensioni per visualizzare la mia cella.

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    //get new width of the screen
    screenRect = [[UIScreen mainScreen] bounds];
    screenWidth = screenRect.size.width;

    //if landscape mode
    if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
    {
        screenDivide = 5;
    }
    else
    {
        screenDivide = 3;
    }

    //reload the collectionview layout after rotating
    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
    [layout invalidateLayout];
}

Quindi ho definito le celle in questo modo

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    screenRect = [[UIScreen mainScreen] bounds];
    screenWidth = screenRect.size.width;

    CGSize elementSize = CGSizeMake(screenWidth/screenDivide, 100);
    return elementSize;
}

Ho un viewcontroller con 2 controller CollectionView.

Vorrei che, a rotazione, solo una delle viste della raccolta si ridimensionasse a una dimensione personalizzata mentre l'altra rimanesse la stessa.

Ho provato a usare:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout  *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
  {    
     // Adjust cell size for orientation
     if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
        return CGSizeMake(170.f, 170.f);
     }
    return CGSizeMake(192.f, 192.f);
}

Tuttavia, ciò cambia semplicemente entrambe le visualizzazioni di raccolta. Come faccio a essere specifico per una sola collezione?


Answer #1

La risposta verificata non è efficiente

Il problema - L'invalidazione del layout in viewWillLayoutSubviews () è un lavoro pesante. viewWillLayoutSubviews () viene chiamato più volte quando viene istanziato un ViewController .

La mia soluzione (Swift) - Incorpora la tua manipolazione delle dimensioni all'interno di UICollectionViewDelegateFlowLayout .

// Keep a local property that we will always update with the latest 
// view size.
var updatedSize: CGSize!

// Use the UICollectionViewDelegateFlowLayout to set the size of our        
// cells.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    // We will set our updateSize value if it's nil.
    if updateSize == nil {
        // At this point, the correct ViewController frame is set.
        self.updateSize = self.view.frame.size
    }

    // If your collectionView is full screen, you can use the 
    // frame size to judge whether you're in landscape.
    if self.updateSize.width > self.updateSize.height {
        return CGSize(width: 170, 170)
    } else {
        return CGSize(width: 192, 192)
    }
}

// Finally, update the size of the updateSize property, every time 
// viewWillTransitionToSize is called.  Then performBatchUpdates to
// adjust our layout.
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    self.updateSize = size
    self.collectionView!.performBatchUpdates(nil, completion: nil)
}

Answer #2

Ho gestito questo rilevando il cambiamento di orientamento nel setBounds: metodo. Eseguiamo la sottoclasse di UICollectionView e sovrascriviamo setBounds: method (vedi sotto). In flowLayoutForGallerySize creiamo un nuovo UICollectionViewFlowLayout con spaziatura e itemSize diversi a seconda delle dimensioni della vista di raccolta.

- (void)setBounds:(CGRect)bounds
{
    // detect orientation changes and update itemSize in the flow layout
    CGSize oldSize = self.bounds.size;

    [super setBounds:bounds];

    BOOL wasLandscape = (oldSize.width > oldSize.height);
    BOOL nowLandscape = (bounds.size.width > bounds.size.height);

    if (wasLandscape != nowLandscape) {
        // create a new flow layout object for the new gallery size
        self.flowLayout = [self flowLayoutForGallerySize:bounds.size];

        // change to the new flow layout
        [self setCollectionViewLayout:self.flowLayout animated:NO];

        DLog(@"orientation change to %@", NSStringFromCGSize(bounds.size));
    }
}

Answer #3

La domanda era, come separare due viste di raccolta in sizeForItemAtIndexPath. Perché non è qualcosa di simile?

 func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

    if collectionView == firstCollectionView{

            return CGSize(width: self.frame.width/3, height: 40)
       }


    else if collectionView == secondCollectionView{

        return CGSize(width: self.frame.width, height: self.frame.height-2)
    }

    abort()
}

Answer #4

Puoi cambiare la tua dichiarazione if. Dovrai avere un riferimento alle viste della collezione

if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && collectionView == self.firstCollectionView) {
   return CGSizeMake(170.f, 170.f);
}

Answer #5

Con la nuova API da iOS 8 sto usando:

Swift 3:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    updateCollectionViewLayout(with: size)
}

private func updateCollectionViewLayout(with size: CGSize) {
    if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
        layout.itemSize = (size.width < size.height) ? itemSizeForPortraitMode : itemSizeForLandscapeMode
        layout.invalidateLayout()
    }
}

Objective-C:

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

- (void)updateCollectionViewLayoutWithSize:(CGSize)size {
        UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
        layout.itemSize = (size.width < size.height) ? itemSizeForPortraitMode : itemSizeForLandscapeMode;
        [layout invalidateLayout];
}






uicollectionview