LoginSignup
121
98

More than 5 years have passed since last update.

CoordinatorLayoutでヘッダー隠す時の知見を得た話

Last updated at Posted at 2016-08-16

画面をスクロールした際にヘッダーを隠すような挙動をCoordinatorLayoutで実装できます。
最近、とあるアプリの画面にこの挙動を実装した際にいろいろ試行錯誤したので、「こうやったらヘッダーがうまく隠れてくれたぜイェーイ」ってなった例や、「ここでこうやったらレイアウトも崩れなかったぜイェーイ」ってなったテンションのままで書いてます。

ヘッダーを隠すために

スクロールしたらヘッダーを隠せるようにするUIを作るための基礎知識とかです。
とりあえずこの内容が把握出来てると、あれこれしてるうちになんとなくできる。

スクロールするレイアウト

CoordinatorLayoutでスクロール時にヘッダーを隠す挙動を行いたい際は、スクロールする部分がNestedScrollViewRecyclerViewである必要があります。
ここをScrollViewとかListViewの状態で「ヘッダーが・・・隠れない・・・!」ってなった人もいるかもしれないですね。

とりあえずCoordinatorLayoutのリファレンスを見に行ってもこの辺りは記載されておらず、AppBarLayoutの方に書かれているので、初めてする人だと引っかかる人もいるかもしれません。

あと、「ひとまずこのレイアウトをスクロールしたらヘッダーを隠したいぜ」という場合ですが、そのときは「スクロールしたいレイアウト」を子にもっている、「隠したいヘッダーを子レイアウトに持つCoordinatorLayout」の子レイアウトにつけておきましょう。 自分で書いておいてあれだけどめっちゃわかりにくいな・・・。

隠すヘッダー

隠したいヘッダー部分は、AppBarLayoutの要素内に配置する必要があります。
あと、このAppBarLayoutCoordinatorLayoutの直下になければいけません。

AppBarLayout内にヘッダーを配置し、次のようにapp:layout_scrollFlags属性を設定すると、設定した値に従ってスクロール時にAppBarLayoutが隠れてくれるナイスなレイアウトになってくれます。

<AppBarLayout ...>
    <ToolBar ...
        app:layout_scrollFlags="scroll|enterAlways"
    />
</AppBarLayout>

上のサンプルだと、下方向にスクロールするとAppBarLayoutが隠れて、上方向にスクロールすることでAppBarLayoutが表示されるようになります。

layout_scrollFlagsに指定できるフラグについてはこちらをどうぞ。

基本を抑えたうえで

スクロール時にヘッダーを隠すレイアウトを作成するための基礎知識はこんなところです。
ただ、スクロールするレイアウトの階層が深いところにあったり、別のレイアウトファイルをincludeしていたり、フラグメントであった場合にちゃんと隠れてくれるのか?というところは一度試してみないとわからないところです。

次の画像のようなレイアウトで、Toolbarを隠すようなアプリを目標にして、
そういった場合についていくつか試してみたので、参考例として一覧をあげていきます。

behavior概要_skiched.png

成功例

スクロールするレイアウトxmlがヘッダーのあるレイアウトxmlと別のとき

// TODO それっぽいレイアウト(隠すヘッダーを示す)

res/layout/activity_main.xml
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.v7.widget.Toolbar
                ...
                app:layout_scrollFlags="scroll|enterAlways"/>  

        </android.support.design.widget.AppBarLayout>

        <include layout="@layout/view_pager" />

    </android.support.design.widget.CoordinatorLayout>

</LinearLayout>

res/layout/view_pager.xml
<android.support.v4.widget.NestedScrollView
    android:id="@+id/pager"
    android:layout_below="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <!-- 中略 -->

</android.support.v4.widget.NestedScrollView>

behavior_success01_480.gif

AppBarLayoutにスクロール時に隠したいものと隠したくないものを含みたい

res/layout/activity_main.xml
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.v7.widget.Toolbar
                ...
                app:layout_scrollFlags="scroll|enterAlways"/>  

            <android.support.design.widget.TabLayout
                android:id="@+id/tab"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

            </android.support.design.widget.TabLayout>

        </android.support.design.widget.AppBarLayout>

        <include layout="@layout/view_pager" 
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

    </android.support.design.widget.CoordinatorLayout>

</LinearLayout>

res/layout/view_pager.xml
<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_below="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

</android.support.v4.view.ViewPager>

behavior_success02_480.gif

失敗例

AppBarLayoutが「1. 隠したくないもの、2. 隠したいもの」で構成されてる

res/layout/activity_main.xml
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.v7.widget.Toolbar
                .../>

            <android.support.design.widget.TabLayout
                android:id="@+id/tab"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_scrollFlags="scroll|enterAlways">

            </android.support.design.widget.TabLayout>

        </android.support.design.widget.AppBarLayout>

        <include layout="@layout/view_pager" />

    </android.support.design.widget.CoordinatorLayout>

</LinearLayout>

res/layout/view_pager.xml
<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_below="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

</android.support.v4.view.ViewPager>

behavior_fail_480.gif

上記のような例だと、スクロール時にヘッダーを隠す動作が実行されません。
この場合、AppBarLayout内の一番上にある隠したくないViewを、さらに上位の階層に移すことで解決するほかないと思います。

(※まあこんなUIになる場合に、一番上の隠したくないViewはそれ以下のLayoutとは別の責務を持つことが多いと思うので同じレイアウトファイルに収まってるのがおかしいのかな、とも思います)

しめ

という感じで成功例ふたつ失敗例ひとつという感じで紹介しました。
この先すすめていくとBehaviorを自作する話になってくるのですが、これは後日で。

121
98
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
121
98