UICollectionViewのレイアウト変更について

iOS 7から新しく追加されたAPIを使い、UICollectionViewのレイアウト変更をUINavigationViewControllerと連携させる方法について説明します。


UICollectionViewのレイアウトを変更する際、UICollectionViewのuseLayoutToLayoutNavigationTransitionsプロパティを使うと、UINavigationControllerと連携することができます。 UINavigationControllerと連携することで、実装が安易になる、UIが分かりやすい、といったメリットがあります。

以下、useLayoutToLayoutNavigationTransitionsプロパティについて説明している、ドキュメントの冒頭です。


useLayoutToLayoutNavigationTransitions

This property helps facilitate transitions between two or more collection view controllers using a navigation controller. 


useLayoutToLayoutNavigationTransitionsプロパティを使った場合

useLayoutToLayoutNavigationTransitionsプロパティを使わない場合


Code Example


// Cooperate with navigation controller to switch collection view layout
/////////////////////////////////////////////////////////////////////////////////
newCollectionViewcontroller.useLayoutToLayoutNavigationTransitions = YES;
/////////////////////////////////////////////////////////////////////////////////

// Push collection view controller
[self.navigationController pushViewController:newCollectionViewcontroller animated:YES];

useLayoutToLayoutNavigationTransitionsプロパティをYESに設定し、NavigationControllerにCollectionViewControllerをプッシュします。
プッシュするとレイアウトがアニメーションを伴って変更されます。
このとき、ナビゲーションバーに戻るボタンが表示され、表示された戻るボタンをタップすることで元のレイアウトに戻すことが出来ます。

注意点

※コントローラをプッシュしていますが、最初のCollectionViewが使い回されているようです。

検証ログ

-[CollectionViewController viewWillAppear:] : 47
------------------------------------------
self.navigationController.viewControllers.count : 1
self : <CollectionViewController: 0x10e81c1c0>
self.collectionView : <UICollectionView: 0x10c04a800; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x10ae79ec0>; layer = <CALayer: 0x10ae77f90>; contentOffset: {0, -64}> collection view layout: <UICollectionViewFlowLayout: 0x10e81b830>
self.collectionView.dataSource : <CollectionViewController: 0x10e81c1c0>
self.collectionView.delegate : <CollectionViewController: 0x10e81c1c0>
-[CollectionViewController viewWillAppear:] : 47
------------------------------------------
self.navigationController.viewControllers.count : 2
self : <CollectionViewController: 0x108fd3e70>
self.collectionView : <UICollectionView: 0x10c04a800; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x10ae79ec0>; layer = <CALayer: 0x10ae77f90>; contentOffset: {0, -64}> collection view layout: <UICollectionViewFlowLayout: 0x10e81b830>
self.collectionView.dataSource : <CollectionViewController: 0x10e81c1c0>
self.collectionView.delegate : <CollectionViewController: 0x10e81c1c0>
-[CollectionViewController viewWillAppear:] : 47
------------------------------------------
self.navigationController.viewControllers.count : 3
self : <CollectionViewController: 0x10ad18f00>
self.collectionView : <UICollectionView: 0x10c04a800; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x10ae79ec0>; layer = <CALayer: 0x10ae77f90>; contentOffset: {0, -38}> collection view layout: <UICollectionViewFlowLayout: 0x108fd3ad0>
self.collectionView.dataSource : <CollectionViewController: 0x10e81c1c0>
self.collectionView.delegate : <CollectionViewController: 0x108fd3e70>
-[CollectionViewController viewWillAppear:] : 47
------------------------------------------
self.navigationController.viewControllers.count : 4
self : <CollectionViewController: 0x108fdc660>
self.collectionView : <UICollectionView: 0x10c04a800; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x10ae79ec0>; layer = <CALayer: 0x10ae77f90>; contentOffset: {0, -3}> collection view layout: <UICollectionViewFlowLayout: 0x10ad18b60>
self.collectionView.dataSource : <CollectionViewController: 0x10e81c1c0>
self.collectionView.delegate : <CollectionViewController: 0x10ad18f00>
-[CollectionViewController viewWillAppear:] : 47
------------------------------------------
self.navigationController.viewControllers.count : 5
self : <CollectionViewController: 0x10ae06110>
self.collectionView : <UICollectionView: 0x10c04a800; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x10ae79ec0>; layer = <CALayer: 0x10ae77f90>; contentOffset: {0, 102}> collection view layout: <UICollectionViewFlowLayout: 0x108f9db00>
self.collectionView.dataSource : <CollectionViewController: 0x10e81c1c0>
self.collectionView.delegate : <CollectionViewController: 0x108fdc660>

Not cooperating UINavigationController

ナビゲーションコントローラーと連動させずにレイアウトを変更するには、以下のメソッドを使用します。

  • (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated; (Available IOS 6)
  • (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated completion:(void (^)(BOOL finished))completion; (Available iOS 7)