Cambiar el tamaño de UICollectionViewCell en diferentes orientaciones del dispositivo


Estoy usando un UICollectionView con UICollectionViewFlowLayout.

Establezco el tamaño de cada celda a través de la

collectionView:layout:sizeForItemAtIndexPath:

Al cambiar de vertical a horizontal, me gustaría ajustar el tamaño de cada celda para que se ajuste completamente al tamaño de la vista de colección, sin dejar espacio de relleno entre las celdas.

Preguntas:

1) ¿Cómo cambiar el tamaño de una celda después de un evento de rotación?

2) Y, aún mejor, cómo hacer el diseño donde las celdas siempre se ajustan a todo el tamaño de la ¿pantalla?

Author: Blaszard, 2012-11-26

6 answers

1) Puede mantener e intercambiar varios objetos de presentación, pero hay una forma más sencilla. Simplemente agregue lo siguiente a su subclase UICollectionViewController y ajuste los tamaños según sea necesario:

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

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [self.collectionView performBatchUpdates:nil completion:nil];
}

Llamar a -performBatchUpdates:completion: invalidará el diseño y redimensionará las celdas con animación (solo puede pasar nil a ambos parámetros de bloque si no tiene ajustes adicionales que realizar).

2) En lugar de codificar los tamaños de los elementos en -collectionView:layout:sizeForItemAtIndexPath, simplemente divida la altura o el ancho de los límites de collectionView por el número de celdas que desea caber en la pantalla. Utilice la altura si su collectionView se desplaza horizontalmente o la anchura si se desplaza verticalmente.

 200
Author: followben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-20 22:50:01

Si no desea animaciones adicionales traídas por performBatchUpdates:completion:, simplemente use invalidateLayout para forzar la recarga de collectionViewLayout.

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [self.collectionView.collectionViewLayout invalidateLayout];
}
 33
Author: Hai Feng Kao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-08 16:20:31

Solucioné usando dos UICollectionViewFlowLayout. Uno para retrato y otro para paisaje. Los asigno a mi collectionView dinámicamente en-viewDidLoad

self.portraitLayout = [[UICollectionViewFlowLayout alloc] init];
self.landscapeLayout = [[UICollectionViewFlowLayout alloc] init];

UIInterfaceOrientation orientationOnLunch = [[UIApplication sharedApplication] statusBarOrientation];

if (UIInterfaceOrientationIsPortrait(orientationOnLunch)) {
    [self.menuCollectionView setCollectionViewLayout:self.portraitLayout];
} else {
    [self.menuCollectionView setCollectionViewLayout:self.landscapeLayout];
}

Entonces simplemente modifiqué mis métodos collectionViewFlowLayoutDelgate como este

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    CGSize returnSize = CGSizeZero;

    if (collectionViewLayout == self.portraitLayout) {
        returnSize = CGSizeMake(230.0, 120.0);
    } else {
        returnSize = CGSizeMake(315.0, 120.0);
    }

    return returnSize;
}

Último cambio de un diseño a otro en rotación

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    if (UIInterfaceOrientationIsPortrait(fromInterfaceOrientation)) {
        [self.menuCollectionView setCollectionViewLayout:self.landscapeLayout animated:YES];
    } else {
        [self.menuCollectionView setCollectionViewLayout:self.portraitLayout animated:YES];
    }
}
 13
Author: Fiveagle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-03 16:33:44

Hay una manera sencilla de establecer el tamaño de la celda de la vista de colección:

UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
layout.itemSize = CGSizeMake(cellSize, cellSize);

No estoy seguro de si es animable.

 8
Author: Dannie P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-31 15:21:24

Swift: Celda de vista de colección que es n % de la altura de la pantalla

Necesitaba una celda que tuviera un cierto porcentaje de altura de vistas y que redimensionara con la rotación del dispositivo.

Con la ayuda de arriba, aquí está la solución

override func viewDidLoad() {
    super.viewDidLoad()
    automaticallyAdjustsScrollViewInsets = false
    // if inside nav controller set to true
}

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

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: 100, height: collectionView.frame.height * 0.9)
}
 7
Author: DogCoffee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-07 23:50:56

Si está utilizando autolayout.Solo necesita invalidate layout en su controlador de vista al girar y ajustar offset en su subclase de diseño de flujo.

Entonces, En su controlador de vista -

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

Y en su FlowLayout Subclass

override func prepareLayout() {
    if self.collectionView!.indexPathsForVisibleItems().count > 0{
    var currentIndex : CGFloat!
    currentIndex = CGFloat((self.collectionView!.indexPathsForVisibleItems()[0] as! NSIndexPath).row)
    if let currentVal = currentIndex{
        self.collectionView!.contentOffset = CGPointMake(currentIndex * self.collectionView!.frame.width, self.collectionView!.contentOffset.y);
    }   
    }     
}
 2
Author: toofani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-16 11:43:40