2013-09-24 3 views
41

У меня есть viewcontroller с 2 контроллерами CollectionView.Как определить размер CollectionView при повороте

Я хотел бы повернуть, что только один из видов коллекции изменяет размер до нестандартного размера, в то время как другой остается неизменным.

Я пытался использовать:

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

Однако это только изменяет оба collectionviews. Как мне получить конкретную информацию только для одной коллекции?

ответ

62

Heres моих 2 цента - потому что ваши размеры товаров статичны почему вы не установите размер элемента на collectionViewLayout?

Это будет скорее сделать, а не ожидать, что представление коллекции вызовет его метод делегирования для каждой ячейки.

viewWillLayoutSubviews может использоваться для обнаружения вращения на контроллерах вида. invalidateLayout можно использовать на макете просмотра коллекции, чтобы заставить его снова подготовить макет, заставив его расположить элементы с новыми размерами в этом случае.

- (void)viewWillLayoutSubviews; 
{ 
    [super viewWillLayoutSubviews]; 
    UICollectionViewFlowLayout *flowLayout = (id)self.firstCollectionView.collectionViewLayout; 

    if (UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation)) { 
     flowLayout.itemSize = CGSizeMake(170.f, 170.f); 
    } else { 
     flowLayout.itemSize = CGSizeMake(192.f, 192.f); 
    } 

    [flowLayout invalidateLayout]; //force the elements to get laid out again with the new size 
} 

редактировать: обновлена ​​например Swift2.0

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 

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

    if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) { 
    flowLayout.itemSize = CGSize(width: 170, height: 170) 
    } else { 
    flowLayout.itemSize = CGSize(width: 192, height: 192) 
    } 

    flowLayout.invalidateLayout() 
} 
+1

Это работает, но теперь я получаю предупреждение о том, что: Несовместимые типы указателей, инициализирующие 'UICollectionViewFlowLayout *' с выражением типа 'UICollectionViewLayout *' –

+0

, вам нужно будет нарисовать collectionViewLayout, теперь я отрегулирую ответ @RobertFarr –

+1

Уважаю, работал как шарм. –

-2

Я обработал это, обнаружив изменение ориентации в методе setBounds:. Мы подклассифицируем UICollectionView и переопределим метод setBounds: (см. Ниже). В flowLayoutForGallerySize мы создаем новый UICollectionViewFlowLayout с различными интервалами и itemSize в зависимости от размера коллекции.

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

код я отвечал отлично работает для изменения размера, однако я хочу, чтобы только изменить размер одного из 2 отдельные представления коллекции –

+1

Почему бы вам просто не взглянуть на параметр collectionView:, чтобы увидеть, какой из них передается, и применять его только тогда, когда он правильный? – progrmr

3

Вы можете изменить инструкцию if. Вам нужно будет иметь ссылку на мнения, сбор

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

С новым API так IOS 8 Я использую:

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

Цель-С:

- (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]; 
} 
1

Вопрос состоял в том, как разделить два вида коллекций в sizeForItemAtIndexPath. Почему просто не что-то вроде этого?

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

верифицированной Ответ не является эффективным

Проблема - утратившими силу макет в viewWillLayoutSubviews() тяжелая работа. viewWillLayoutSubviews() вызывается несколько раз, когда создается объект ViewController.

Моего решения (Swift) - Встраивание ваших манипуляций размера в 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) 
} 
+6

Вместо того, чтобы сохранять размер и вызывать executeBatchUpdates, все, что вам нужно сделать, это вызвать self.collectionView! .CollectionViewLayout.invalidateLayout() Затем в sizeForItemAtIndexPath просто получить новые границы из view/collectionView –

1

Я решил эту проблему, проверив поворот устройства, а затем перезагрузив макет. Проверка размера экрана и использование этого размера для отображения моей ячейки.

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

Тогда я определил клетки как этот

- (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; 
} 
Смежные вопросы