こんにちは!株式会社メモリアインクのふくしまです!
この記事ではユーザーの操作性を高めるための一つのテクニックとして、スクロール時にヘッダーを非表示にする方法があります。この方法について詳しく解説していきます。
この記事を読んで分かること…
・スクロール時にヘッダーを非表示にする実装方法
・基準点からのスクロールした距離の求め方
開発環境
・Swift 5.9
・Xcode 15
スクロール時にヘッダーを非表示にする実装方法
概要
ユーザーがスクロール操作に応じてヘッダーを非表示にすることでンテンツにより多くのスペースを確保し、ユーザーエクスペリエンスを向上させることができます。
今回は、テーブルリストを作成し、上下にスクロールすることでヘッダーを表示・非表示にする実装を例に解説していきます。
前提
・StoryboardでUIView(ヘッダー部分)とUITableView(テーブルリスト部分)を配置し、ViewControllerに紐づけておきましょう。
サンプルコード
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var headerView: UIView!
var isHeaderHidden = false
var previousScrollOffset: CGFloat = 0
let items = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12", "Item 13", "Item 14", "Item 15", "Item 16", "Item 17", "Item 18", "Item 19", "Item 20"]
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
private func setupTableView() {
tableView.dataSource = self
tableView.delegate = self
// UITableViewのセル登録
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
// MARK: - UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = items[indexPath.row]
return cell
}
// MARK: - UITableViewDelegate
// 必要に応じてUITableViewDelegateメソッドをここに追加
// MARK: - スクロールイベントの処理
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let scrollDiff = scrollView.contentOffset.y - previousScrollOffset
if scrollDiff > 0 && scrollView.contentOffset.y > 0 {
if !isHeaderHidden {
UIView.animate(withDuration: 0.3, animations: {
self.headerView.transform = CGAffineTransform(translationX: 0, y: -self.headerView.frame.height)
self.adjustTableViewInset(top: self.headerView.frame.height)
})
isHeaderHidden = true
}
} else if scrollDiff < 0 && scrollView.contentOffset.y < self.headerView.frame.height {
if isHeaderHidden {
UIView.animate(withDuration: 0.3, animations: {
self.headerView.transform = .identity
self.adjustTableViewInset(top: 0)
})
isHeaderHidden = false
}
}
previousScrollOffset = scrollView.contentOffset.y
}
private func adjustTableViewInset(top: CGFloat) {
let insets = UIEdgeInsets(top: top, left: 0, bottom: 0, right: 0)
tableView.contentInset = insets
tableView.scrollIndicatorInsets = insets
}
}
サンプルコードの説明
・3行目:UIViewController
、UITableViewDataSource
、およびUITableViewDelegate
プロトコルを実装することを宣言します。これにより、テーブルビューのデータソース(データ提供)とデリゲート(イベント管理)の両方の役割をこのビューコントローラが担うことになります。
・6行目:ヘッダーの表示状態を追跡するためのブール変数isHeaderHidden
・7行目:前回のスクロールオフセット位置を記録するための変数previousScrollOffse
・37-38行目:スクロールイベントが発生したときに呼ばれるデリゲートメソッドを実装します。スクロールの差分を計算しています。
・40行目:ユーザーが下にスクロールしているかどうかを判断します。この条件は、スクロールが下向きであり、かつスクロールビューが最上部よりも下にある場合に真となります。
・41-47行目:ヘッダーがまだ非表示でない場合、アニメーションを使ってヘッダーを上にスライドさせ、テーブルビューのcontentInset
を調整するメソッドadjustTableViewInset
(60-64行目で定義)を使用。
・48行目:ユーザーが上にスクロールし、スクロール位置がヘッダーの高さよりも小さい場合の条件もチェックしています。
・49-55行目:ヘッダーが非表示の場合、アニメーションを使ってヘッダーを元の位置に戻し、テーブルビューのcontentInset
を再調整します。最後に、現在のスクロールオフセットをpreviousScrollOffset
に記録します。
・60-64行目:テーブルビューのcontentInset
とscrollIndicatorInsets
を調整するためのヘルパーメソッドを実装します。これにより、ヘッダーの表示状態に応じてテーブルビューの上部の余白を適切に設定します。
動作確認
それでは動作を確認してみましょう!
まとめ
いかがでしたか?
この記事では、Swiftを使ったiOS開発において、スクロール時にヘッダーを非表示にする方法を詳細に解説しました。サンプルコードを通じて、具体的な実装方法を学ぶことができました。
この記事が皆様の開発ライフの一助になれれば幸いです!
この記事があなたのスキルアップに役立ったなら、次のキャリアステップを踏み出す絶好の機会かもしれません。エンジニアとしてのさらなる成長と挑戦を求めるなら、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】
コメント