要件(ゴール)
・tableViewで一覧から詳細へ遷移できる
・一覧で下へスクロールした際はNavigationBarを非表示/上へスクロールした際はNavigationBarを表示
・詳細ではNagigationBarを隠さない
・詳細から一覧へ戻った際は、NavigationBarの表示/非表示の状態が維持されている
背景
http://animane.hatenablog.com/entry/2016/02/04/144458
で紹介されているようなライブラリもあるのだが、
いざプロジェクトに組み込んで見ると、思うような挙動にならなかったり、
swiftにそもそも対応してなかったりした。
調べてみると自力で実装でもそんなに大変ではなさそうなので、
実装してまとめて記事にしました。
環境
OS: iOS9~iOS12まで確認済
言語:Swift4.2
前提
tableViewで一覧から詳細へ遷移できるプロジェクトがあること
サンプルプロジェクト
こちらを手元で確認していただけながら、読み進めていただければと思います。
https://github.com/suzuhiroruri/scrollHidingNavbar
手順
下記変数を入れる
/// スクロール開始地点
var scrollBeginPoint: CGFloat = 0.0
/// navigationBarが隠れているかどうか(詳細から戻った一覧に戻った際の再描画に使用)
var lastNavigationBarIsHidden = false
スクロール開始時にスクロール開始地点を習得
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
scrollBeginPoint = scrollView.contentOffset.y
}
scrollViewDidScrollでスクロール量を検知
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let scrollDiff = scrollBeginPoint - scrollView.contentOffset.y
updateNavigationBarHiding(scrollDiff: scrollDiff)
}
navigationBarの表示/非表示を更新メソッド boundaryValueはスクロールの閾値なのでお好みで設定してください。
func updateNavigationBarHiding(scrollDiff: CGFloat) {
let boundaryValue: CGFloat = 0.0
/// navigationBar表示
if scrollDiff > boundaryValue {
navigationController?.setNavigationBarHidden(false, animated: true)
lastNavigationBarIsHidden = false
return
}
/// navigationBar非表示
if scrollDiff < -boundaryValue {
navigationController?.setNavigationBarHidden(true, animated: true)
lastNavigationBarIsHidden = true
return
}
}
詳細画面から戻ってきた際にNavigationBarの表示状態を以前の状態に更新
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if lastNavigationBarIsHidden {
self.navigationController?.setNavigationBarHidden(true, animated: false)
}
}
デフォルトだと詳細遷移の際、NavigationBarが非表示になってしまうので、表示させる
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.setNavigationBarHidden(false, animated: false)
}
tableViewのTopをSafeAreaに設定するとiOS10系の端末でtableの表示がずれてしまう場合があるので、 topをViewのTopにする。 またそれだとiPhoneX系の端末でtableViewをスクロールした時にSafaAreaにかぶるので、 SafeAreaを隠すビューを入れる。 ![スクリーンショット 2018-09-28 17.19.59.png](https://qiita-image-store.s3.amazonaws.com/0/13599/a053763c-f613-ba26-08c0-dcab1b5aa6c5.png)
あとがき
navigationController?.hidesBarsOnSwipe = true
https://qiita.com/ken0nek/items/9e293bd7d730191cdbc5
で動かないこともないんですけど、
微妙なスクロールだとSwipeと検知されないこともあったり、
OS?機種?によってNavigationBarが表示できないこともあったので、
今回はスクロールベースで検知してNavigationBarの表示を切り替えるようにしました。
訂正等ありましたら、よろしくお願いします。