Tiwtter等のアプリでよくあるプロフィール画面のカバー画像を下に引っ張ると拡大されるPrallaxHeader機能(っていうんですかね?)ですが、
実はこれめちゃくちゃ簡単に実装できます。
GitHubにサンプルもあります。
環境
Xcode Version 11.4.1 (11E503a)
Swift version 5.2.2 (swiftlang-1103.0.32.6 clang-1103.0.32.51).
実装
使用しているはUITableViewとtableHeaderViewです。
まあこの構成はよくあると思いますが、ポイントはヘッダー画像をtableHeaderViewに入れないことです。
DebugViewHierarchyでみるとよくわかると思います。
Interface Builder
- UIViewController.View
- UIImageView ←これがTwitterでいう下に引っ張ると拡大されるカバー画像になる。
- UITableView ←透明にする。
- UIView ←これがtableHeaderView
- UIView ←これがカバーイメージの上にかぶる部分。透明にする。
- UIView ←ヘッダーに載せたいコンテンツを載せるView。背景色をつける。
- UILabel ←ヘッダーに載せたいコンテンツ。今回は適当にラベル。
上記の構成でViewを配置し、カバー画像のUIImageView下記のAutoLayoutをかけます。
- Align Top to SuperView Top
- Align Center X
- 任意のAspect Ratio
- Height Equal = 適当な数値
カバーイメージの上にかぶる部分の透明なViewに下記のAutoLayoutをかけます。
- Align Top to SuperView Top
- Trailing Space To SuperView
- Leading Space To SuperView
- カバー画像と同じAspect Ratio
あとは実装したいUIにあわせます。
コード
カバー画像Viewの Align Top to SuperView Top
と - Height Equal = 適当な数値
をIBOutletで接続します。
@IBOutlet private var coverImageHeightConstraint: NSLayoutConstraint!
@IBOutlet private var coverImageTopConstraint: NSLayoutConstraint!
- Height Equal = 適当な数値
のままだと高さがずれるのでデフォルトの高さをセットしてあげてください。
private var defaultCoverImageHeight: CGFloat { return self.view.frame.width / 3 }
override func viewDidLoad() {
super.viewDidLoad()
self.coverImageHeightConstraint.constant = self.defaultCoverImageHeight
}
最後に、UITableViewDelegate.scrollViewDidScroll(_ scrollView: UIScrollView)
の中にcontentsOffset.yの変化に応じて適当な値をIBOutletで接続した制約に与えてあげれば終わりです。
extension ViewController: UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.coverImageHeightConstraint.constant = max(self.defaultCoverImageHeight, -(scrollView.contentOffset.y - self.defaultCoverImageHeight))
self.coverImageTopConstraint.constant = min(0, -scrollView.contentOffset.y)
}
}
おわり
UITableViewの下にUIImageViewを配置し、必要な箇所の背景色を透明にして制約をいじるだけなので割と既存の実装に反映させやすいと思います。
また、スクロール位置に合わせてブラーを追加する機能等も簡単に追加できると思うのでおすすめです。