TableViewのヘッダーはスクロールしても画面内に止まるようになっています。
それを無理やり画面に残らないようにする方法は下記の地道な方法があります。
セクションヘッダが画面上に残らないようにする方法
safeAreaを考慮しない場合
private let sectionHeaderHeight: CGFloat = 8
func scrollViewDidScroll(_ scrollView: UIScrollView) {
/// sectionHeaderが上部に残らないようにする
let offsetY = scrollView.contentOffset.y
if offsetY <= sectionHeaderHeight && offsetY >= 0 {
scrollView.contentInset = UIEdgeInsets(top: -offsetY, left: 0, bottom: 0, right: 0)
} else if offsetY >= sectionHeaderHeight {
scrollView.contentInset = UIEdgeInsets(top: -sectionHeaderHeight, left: 0, bottom: 0, right: 0)
}
}
しかし、これだとiPhone Xの場合にsafeArea上で思った通りに動きません。
tableViewにはios11から safeAreaInsets
というものが追加されおり、この safeAreaInsets
と contentsInsets
を合算した adjustedContentInset
を使ってヘッダー位置の調整を行なっています。
よって、上記サンプルのcontentOffsetにsafeAreaの概念を入れてあげます。
safeAreaを考慮したサンプル
private let sectionHeaderHeight: CGFloat = 8
func scrollViewDidScroll(_ scrollView: UIScrollView) {
/// sectionHeaderが上部に残らないようにする
let offsetY = scrollView.contentOffset.y
let safeAreaInset: CGFloat
if #available(iOS 11.0, *) {
safeAreaInset = scrollView.safeAreaInsets.top
} else {
safeAreaInset = 0
}
let top: CGFloat
if offsetY > sectionHeaderHeight{
/// 一番上のheaderの最下部が画面外へ出ている状態
top = -(safeAreaInset + sectionHeaderHeight)
} else if offsetY < -safeAreaInset {
/// 初期状態からメニューを下に引っ張っている状態
top = 0
} else {
/// safeArea内を一番上のheaderが移動している状態
top = -(safeAreaInset + offsetY)
}
scrollView.contentInset = UIEdgeInsets(top: top, left: 0, bottom: 0, right: 0)
}