今インターン先でやってる開発の中で、
UINavigationController
に関してちょっと立ち止まったところがあったので
メモしておきます。
躓きポイント
ページングビューを簡単に実装できるParchment
というライブラリを使ったPagingViewControllerをNavigationControllerの元に配置しようとしたら、対象のViewがNavigationBarの下に潜り込んでメニューバーなどが見えなくなりました。
これを解消するべく調べてみたら以下の記事がヒット↓
// PagingViewController override func viewDidLoad() { super.viewDidLoad() self.navigationController?.navigationBar.isTranslucent = false }
これを参考にPagingViewControllerにこんなコード追加したらとりあえず直ったのですが、isTranslucent
ってプロパティは何ぞや?ということで少し調べてみました。
UINavigationController.navigationBar.isTranslucentについて
これはUINavigationBar
、のプロパティで、ナビゲーションバーが半透明になったときにナビゲーションバーの下のコンテンツを表示するように設定します。デフォルト値はtrue
です。
このデフォルト値がtrueなのにも関わらず、普通にナビゲーションバーを設置しても後ろが透過されてるように見えないのは、
- レイアウトの中に不透明なナビゲーションバーが含むかどうかを示す
extendedLayoutIncludesOpaqueBars
というプロパティのデフォルト値がfalseである - 通常SafeAreaはバーの下から設定されている
- ナビゲーションバーの後ろはデフォルト背景が設定されている といった理由があります。
つまり、isTranslucent
がtrueであることを活かしNavigationBarを透過させて下のコンテンツを表示するには、まずextendedLayoutIncludesOpaqueBars
プロパティをtrueにする必要がありそうです。
実は通常はこの設定だけでナビゲーションバーの下のコンテンツが見えるようになるんですが、それが叶うのはedgesForExtendedLayout
というプロパティがデフォルトで.all
であるということが前提としてあるためです。
edgesForExtendedLayout
は端的にいうと、Viewがどの端まで伸びているかを示すもので、以下の項目があります。
public static var top: UIRectEdge { get } public static var left: UIRectEdge { get } public static var bottom: UIRectEdge { get } public static var right: UIRectEdge { get } public static var all: UIRectEdge { get }
デフォルトは.all
に設定されています。StoryBoardからも設定できて、複数項目も設定できます。全部選ぶと.all
と同じとみなされるみたいです。
ここまでをまとめると、通常であればisTranslucent
がtrueであってもナビゲーションバーの下にViewが潜り込んでしまうことは無いはずなんですが、外部のライブラリ使ったりすると、意図せずしてデフォルト設定が変わっちゃってたりすることもあります。
そんなときに、isTranslucent
をfalseに設定してあげると、
- ナビゲーションバーが無条件に透過されなくなる
- ナビゲーションバーが表示されている状態では、ViewControllerのビューの描画範囲が狭くなる
となり、潜り込んじゃったViewをちゃんと見ることができるようになるみたいです。
ちなみにこれは、TabBarなども持ってるプロパティです。
注意点
この設定を変えると、該当するNavigationController下にある全てのViewに影響が出るので、設定を変えたView以外のViewでレイアウトに多少の影響が出る可能性があります。(ちなみに私はこれいじって他のViewが崩れました)
設定を全部で統一した上で開発を進めるか、viewWillAppear
とかでViewを描画するたびに設定してあげるかすると良さそうです。
間違ってたり足りなかったりしたらご指摘お願いします!