2016-05-21 16 views
6

コレクションビューの境界に基づいてアイテムのサイズが設定されたコレクションビューを実装しています。したがって、たとえば、デバイスを回転させるためにサイズが変更された場合、レイアウトを無効にして、新しいコレクションビューの境界を考慮してセルのサイズを変更する必要があります。私はこれをviewWillTransitionToSize API経由で行っています。サイズ変更時にコレクションビューレイアウトを無効にする適切な方法

これは、ユーザーがコレクションビューを含むビューコントローラ上にモーダルビューコントローラを表示し、デバイスを回転してから閉じてしまうまで機能します。これが発生すると、アイテムのサイズが適切なサイズに更新されませんでした。 viewWillTransitionToSizeが呼び出され、レイアウトは期待どおりに無効化されますが、コレクションビューの境界は依然として古い値です。たとえば、ポートレートからランドスケープに回転するとき、コレクションビューの境界値の高さは、幅よりも大きくなります。なぜそれが当てはまるのか分かりませんが、これがサイズ変更を無効にする最良の方法であるかどうか疑問です。それを行うより良い方法はありますか?

私もUICollectionViewFlowLayoutをサブクラス化しYESを返すためにshouldInvalidateLayoutForBoundsChangeを上書きしようとしたが、何らかの理由で、これはさえモーダルプレゼンテーションせずに回転動作しません。適切なコレクションビュー境界を使用しません。

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

    [self.collectionView.collectionViewLayout invalidateLayout]; 

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> __nonnull context) { 
     [self.collectionView.collectionViewLayout invalidateLayout]; 
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> __nonnull context) { 
     //finished 
    }]; 
} 

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    //collectionView.bounds.size is not always correct here after invalidating layout as explained above 
} 

は、私はまた、完了ブロックでそれをinvaliding試してみたが、それはまだ適切なコレクションビューの境界を使用していません。

viewWillAppearで再度レイアウトを無効にすると、適切なコレクションビュー境界が使用され、モーダルに表示されたビューコントローラで回転する問題が解決されます。しかし、これは必要ではないはずです。おそらく、これが適切にサイズ調整されない他の状況があります。

+0

http://stackoverflow.com/questions/29023473/uicollectionview-invalidate-layout-on-bounds-changesを見ましたか? – ozgur

+0

@ozgur私はすでに、その答えにあるものを試しました。上記で説明した通りです。 – Joey

+0

'viewWillAppear()'で何も更新していませんか? modal viewコントローラが閉じられているときに、上記のシナリオ(モーダルコントローラが終了している間に向きを変える)では、 'viewWillAppear()'に* previous *の向きのフレームを取得し、 'viewDidAppear() '。ですから、私にとっては通常、 'viewWillTransitionToSize'でレイアウトを更新するだけです。 –

答えて

13

私は問題が何であるか知っています。 をanimateAlongsideTransition(アニメーションブロックまたは補完ブロックのいずれか)に呼び出すと、モーダルビューコントローラがフルスクリーン上に表示されていればレイアウトは実際には再計算されません(ただし、現在のコンテキストではそうなります)。しかし、私が行っていたようにアニメーションブロックの外でそれを無効にすると、無効になります。しかし、コレクションビューでは新しいサイズがレイアウトされていないため、その境界の古い値が表示されていた理由がわかります。この動作の理由はinvalidateLayoutで、直ちにレイアウトが再計算されることはなく、次のレイアウトパスで発生するようにスケジュールされています。このレイアウト・パスは、モーダル表示されたビュー・コントローラがフルスクリーン上にある場合には発生しません。レイアウトパスを強制するには、のすぐ後に[self.collectionView.collectionViewLayout invalidateLayout];の直後に、animateAlongsideTransitionブロックの中に依頼してください。これにより、レイアウトが予想どおりに再計算されます。

+0

あなたの答えは私の一日をした..たくさんありがとう! –

関連する問題