#概要
iphoneアプリにおけるモダンなUIを実現するための方法として、いかにApple公式アプリのUIをパクるかは重要です。
iOS11にてAppleの公式UIとしてLargeTitleというものが追加されました。
UINavigationBarが設定されたスクロールビューにてタイトルの位置と大きさをアニメーションでいい感じにしてくれます。
「ミュージック」におけるLargeTitle
しかし、LargeTitleは周囲のUIパーツを正しく扱わないと残念な感じになってしまいます。
今回は実装に取り入れる上で、つまづいた3つの点と解決策をまとめました。
###記事の前提
- iOS11以降
- Master-Detail型の遷移(LargeTitleが設定されたScrollVIew→詳細ビュー)を伴うアプリ
#LargeTitleの実装
LargeTitleは簡単に以下の設定で有効にすることができます.
//title設定
navigationItem.title = "title"
//largeTitle表示
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
//laegeTitle(小)時の文字
navigationController?.navigationBar.titleTextAttributes = [
.foregroundColor: .white
]
//laegeTitle(大)時の文字
navigationController?.navigationBar.largeTitleTextAttributes = [
.foregroundColor: .white,
.font : UIFont.boldSystemFont(ofSize: 26.0)
]
具体的な実装は下記の記事にまとまっています
- [ios11からのNavigationBarを実装する(largeTitleDisplayMode)]
(https://qiita.com/tommy19970714/items/736d74ebb51daf276b2d)
##残念なLargeTitle
しかし、周囲のUIパーツを正しく扱わないと下記のような残念な感じになってしまいます.
具体的には以下の点がかっこ悪いです。
- LargeTitleとNavigationBarの間に残るボーダーライン
- ナビゲーションコントローラでの画面遷移時に黒い背景
- スクロール時にLargeTitleとNavigationBar間にどこかの背景色
#解決策
###LargeTitleとNavigationBarの間に残るボーダーライン
LargeTitleが設定されている場合は大抵の場合無い方がキレイだと思いますが、デフォルトでは消してくれません。
これは、navigationController.navigationBar.shadowImage
に設定されているUIImageです。
//largeTitle時のnavigationBarのボーダを消す。戻す場合はnil代入
navigationController?.navigationBar.shadowImage = UIImage()
また、nilが代入されるとデフォルトのボーダーラインに戻るようです。
画面遷移後もNavigationControllerのインスタンスは残るため、
1画面だけ消したい場合じゃDelegateメソッドなどでnilを代入し直す必要があります。
結論から言えばこいつはNavigationController自身の持っているViewの色です。
これについては情報が少なく、UIパーツ1つ1つの色を変えていくことでようやく発見しました。
そもそもNavigationController自体がViewを持っているという事実が完全に盲点、、、
下記のように、好きな色に変更することができます。遷移先のビューの色と合わせるときれいですね。
//largetitleの適用時の画面遷移でチラ見する黒背景はコイツ
navigationController.view.backgroundColor = .white
###スクロール時にLargeTitleとNavigationBar間にどこかの背景
LargeTitle設定時にスクロールをひっぱった際にどこかの背景が写ってしまいかっこ悪いです。
今回の実装ではCollectionViewを利用していたのですが、LargeTitleの変化アニメーションにひっぱられ、
なんとCollectionViewの背景色のマイナス領域が表示されていました。
CollectionViewに限らず、ScrollView上部とNavigationBarの色を揃えたい時はこの設定が必要です。ケースとしては特殊な例かも知れませんが、備忘録として書いておきます。
CollectionView自体の背景色は変えたくなかったため、
これは適当な高さのCALayerをマイナス領域にAddSublayerすることで解決しました。
//largetitleのスクロール時にcollectionviewの背景色が表示される現象対策
let fillSpaceLayer = CALayer()
fillSpaceLayer.backgroundColor = .white
fillSpaceLayer.frame = CGRect(x:0, y:-100, width: self.view.frame.width, height: 100)
collectionView.layer.addSublayer(fillSpaceLayer)
#まとめ
こんな感じにかっこよくLargeTitleを使いこなすことができました。
//largeTitle表示
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
//laegeTitle(小)時の文字色
navigationController?.navigationBar.titleTextAttributes = [
.foregroundColor: .white
]
//laegeTitle(大)時の文字色
navigationController?.navigationBar.largeTitleTextAttributes = [
.foregroundColor: .white,
.font : UIFont.boldSystemFont(ofSize: 26.0)
]
//largeTitle時のnavigationBarのボーダを消す。戻す場合はnil代入
avigationController?.navigationBar.shadowImage = UIImage()
//largetitleの適用時の画面遷移でチラ見する黒背景はコイツ
navigationController.view.backgroundColor = .white
//largetitleのスクロール時にcollectionviewの背景色が表示される現象対策
let fillSpaceLayer = CALayer()
fillSpaceLayer.backgroundColor = .white
fillSpaceLayer.frame = CGRect(x:0, y:-100, width: self.view.frame.width, height: 100)
collectionView.layer.addSublayer(fillSpaceLayer)