タオルケット体操

サツバツいんたーねっと

ContaienrViewを使ってNavigationController的なものを自作する

珍しくObjective-Cネタです。 まだ筆者のObjective-C力は初めて二ヶ月目レベルなので、間違いを含んでいる可能性が大です。あるいはiOS8で変わるかもしれません。

なお当記事のテクニックはiOS7限定、かつ読者はあらかじめContainerViewの使い方を知っていること前提で話をすすめます。

さて。親に対して、並列に子Viewが存在する場合はNavigationControllerを利用するかと思います。
しかしそんな便利なNavigationControllerですが、見た目のカスタマイズという点では全く融通がききません(試した限りは)。

そこでContainerViewを利用した、よりデザイン的な自由の高いNavigationの仕組みを四苦八苦して作ったのでメモっておきます。
割と頻出で欲しいテクニックなはずなのに、ズバリな方法が全く検索で出て来なかったのであるいは組み込みでもっとスマートが方法があるかもしれませんが、それはそれってことであったら指摘いただきたいです。

とりあえずstoryboardをこんなかんじに準備します。

f:id:hachibeechan:20140722221417p:plain

次に、紫ボタンと赤ボタンに対応させたい子Viewをそれぞれ用意します。
ここで注意したいのは、子ViewをContainerViewとEmbedで結んだりはしない(ていうか出来ない)ということです。なので当然、storyboard上で同じサイズになるとかそういうアレの恩恵は受けられません。
そこらへんはAutoLayoutを駆使していい感じにアレすればいいとおもいます。

こんな感じになります。

f:id:hachibeechan:20140722221922p:plain

次に、ContainerViewにEmbededで繋がっているちっさいViewに紐づくViewControllerを実装して、そのChildViewControllerとして赤と紫を追加します。名前は適当です。

// プロパティ
@interface HCBColorfullViewContainerHandlerController ()
 @property (nonatomic, strong) HCBRedChildView *redView;
 @property (nonatomic, strong) HCBRedChildView *purpleView;
@end

// 初期化
- (void) viewDidLoad {
  [super viewDidLoad];

  self->_redView =
    [self.storyboard instantiateViewControllerWithIdentifier: @"HCBRedChildView"];
  [self addChildViewController: self.redView];

  self->_purpleView =
    [self.storyboard instantiateViewControllerWithIdentifier: @"HCBPupleChildView"];
  [self addChildViewController: self.purpleView];

  // 初期状態で表示されているのは赤色Viewとする
  [self.view addSubview: self.redView.view];
  [self.redView didMoveToParentViewController: self];
}

// topレベルで表示するViewを変更する用のメソッドを定義しておく
- (void) showRedView {
  [self.view addSubview: self.redView.view];
  [self.redView didMoveToParentViewController: self];
}

- (void) showPurpleView {
  [self.view addSubview: self.purple.view];
  [self.purple didMoveToParentViewController: self];
}

後は、親Viewのボタンイベントに合わせてHCBColorfullViewContainerHandlerControllerの各メソッドを読んでやるだけです。

- (IBAction) redButtonTouched: (id) sender {
  [[self.childViewControllers objectAtIndex: 0] showRedView];
}

- (IBAction) purpleItemsButtonTouched: (id) sender {
  [[self.childViewControllers objectAtIndex: 0] showPurpleView];
}

これを使えば、ボタン以外にも色んなイベントや条件に応じて子Viewの表示をパチパチ切り替えられますね? ヤッター!