Material Components for iOS
Material ComponentsはGoogleが提供している、Material Designの実装を助けてくれるコンポーネントライブラリです。
詳しくは、次のページを読みましょう
https://github.com/material-components/material-components-ios
FlexibleHeaderとは
Google純正アプリの詳細画面などでみられる、スクロールに合わせヘッダー部分の高さが動的に変わるデザインに用いられています。
Flexible header
https://material.io/develop/ios/components/flexible-headers/
Swifterの方は、次のShrineというDemoアプリを参考にするのがおすすめです。
https://github.com/material-components/material-components-ios/tree/develop/demos/Shrine
StoryBoardを使って実装して見る
手順は次のようになります。
- 画面全体のContainerとなるViewContorllerを作る
- MDCFlexibleHeaderContainerViewControllerを継承した、UIViewContorllerを作る
- ContentとなるViewContorllerを作る
- Headerを除いた部分、TableViewやCollectionViewなどScrollViewを実装したUIViewContorllerを作る
- HeaderとなるViewを作る
画面全体のContainerとなるViewContorllerを作る
MDCFlexibleHeaderContainerViewControllerを継承したViewControllerを作ります。
StoryBoardから生成することを想定しているので、viewDidLoad()で初期セットを行なっています。getContentViewController()は後ほど作成する、「ContentとなるViewContorller」です。
MDCFlexibleHeaderContainerViewControllerのプロパティ:contentViewControllerにセットします。
class FlexibleHeaderViewController: MDCFlexibleHeaderContainerViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Content部分のViewControllerをセット
let contentVC: ContentViewController = getContentViewController()
self.contentViewController = contentVC
// Header部分のViewを制御するため、headerViewControllerをContentにセット
contentVC.headerViewController = self.headerViewController
contentVC.setupHeaderView()
}
}
ContentとなるViewContorllerを作る
ContentとなるViewControllerは、HeaderのViewとそれを制御するためのMDCFlexibleHeaderViewControllerを参照できるようにします。
class ContentViewController: UITableViewController {
var headerViewController: MDCFlexibleHeaderViewController?
var headerContentView: HeaderView = HeaderView.instantiateFromNib()
}
Headerのスクロールを連動させるために、スクロールのDelegateであるscrollViewDidScrollをつなげます。
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
headerViewController!.scrollViewDidScroll(scrollView)
}
今回の例では「画面全体のContainerとなるViewController」からコールしていますが、Header部分のViewのセットです。HeaderのViewのセットと、その内容となるViewをセットしています。
func setupHeaderView() {
let headerView = headerViewController!.headerView
// ヘッダー部分のサイズセット
headerView.trackingScrollView = self.tableView
headerView.maximumHeight = 200
headerView.minimumHeight = 72
headerView.minMaxHeightIncludesSafeArea = false
headerView.backgroundColor = UIColor.blue
headerView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// ヘッダー部分のコンテンツセット
headerContentView.frame = (headerView.bounds)
headerContentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
headerView.addSubview(headerContentView)
}
HeaderとなるViewを作る
Header部分に表示するViewを作成しましょう。
デメリット
次の公式ページにも説明がありますが、UINavigationControllerとの併用する場合、NavigationBarを自前で制御しないといけません。
スクロール操作できるスペースにも注意が必要です。Header部分を縦スクロールしても動作しません。この辺り、TableViewのみで実装した場合と操作感が変わってしまう恐れがあります。