1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Material Components for iOS のFlexibleHeaderを使ってみた

Posted at

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を作る
Simulator Screen Shot - iPhone 8 - 2018-05-13 at 22.44.22.png

画面全体の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のみで実装した場合と操作感が変わってしまう恐れがあります。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?