CoordinatorLayout + CollapsingToolbarLayoutでToolbarをスクロール時に開
CoordinatorLayoutとMaterialDesignのCollapsingToolbarLayoutを使って、下のようにスクロール時にToolbarを開閉させる方法について書きます。
色が付いていると分かり辛いですが、閉じている状態ではelevationが適用され影が表示されます。白抜きにするとわかりやすいです。
ソースコード
app/build.gradle
dependencies {
implementation 'com.google.android.material:material:1.2.1'
}
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="112dp"
android:fitsSystemWindows="true"
android:minHeight="?actionBarSize"
app:collapsedTitleTextAppearance="@style/AppTextAppearance.CollapsedTitle"
app:expandedTitleGravity="start|bottom"
app:expandedTitleMarginBottom="16dp"
app:expandedTitleMarginStart="16dp"
app:expandedTitleTextAppearance="@style/AppTextAppearance.ExpandedTitle"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<com.google.android.material.appbar.MaterialToolbar
style="@style/AppToolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_arrow_back"
app:title="CollapsingToolbarLayout" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Hello CollapsingToolbarLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
style.xml
<resources>
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="colorOnPrimary">@color/white</item>
</style>
<style name="AppToolbar" parent="Widget.MaterialComponents.Toolbar.Primary">
<item name="android:elevation">0dp</item>
<item name="android:background">@android:color/transparent</item>
</style>
<style name="AppTextAppearance.ExpandedTitle" parent="TextAppearance.Design.CollapsingToolbar.Expanded">
<item name="android:textColor">@color/white</item>
</style>
<style name="AppTextAppearance.CollapsedTitle" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
<item name="android:textColor">@color/white</item>
</style>
</resources>
設定方法
ソースコードから重要な部分だけを抜き出すと以下のようになります。
<androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_height="112dp"
android:minHeight="?actionBarSize"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<com.google.android.material.appbar.MaterialToolbar
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
スクロールによる開閉の設定
- 親レイアウトはCoordinatorLayout
- スクロールにより動的に変わる箇所は AppBarLayout
- スクロール箇所は NestedScrollView(または、RecyclerView)
※ 通常の ScrollView では動かないので注意
CoordinatorLayoutはスクロール操作を検知し、子Viewに伝える役割を持っています。
CollapsingToolbarLayout に app:layout_scrollFlags="scroll|exitUntilCollapsed"
を設定することで、一番上までスクロールした時にのみAppBarLayoutの開閉が行われるようになります。
スクロール箇所は app:layout_behavior="@string/appbar_scrolling_view_behavior"
を指定することでスクロールをCoordinatorLayoutに伝えるようになります。また、スクロール箇所の高さをAppBarLayout分、調整してくれます。
CollapsingToolbarLayoutの高さ
開いた状態(collapsed)の高さは CollapsingToolbarLayout の android:layout_height
。
閉じた状態(expanded)の高さは MaterialToolbar の android:layout_height
。
ここで注意しなければいけないのが CollapsingToolbarLayout の android:minHeight
をツールバーの高さに合わせて設定している点。android:minHeight を設定しない、または、ツールバーの高さと差異がある場合、 開閉が動かなかったり、NestedScrollView がスクロールし切れずに画面下部が切れてしまいます。
ツールバーのピン留め
スクロールした時に MaterialToolbar のNavigationIconやメニューが移動しないように app:layout_collapseMode="pin"
を設定してピン留めしている。
この設定がない場合、ツールバーのNavigationIconやメニューも移動の対象になります。
attributes
開閉時のテキスト属性の設定等できます。詳細は公式サイトへ。
最後に
今回はシンプルにToolbarの開閉のみでしたが、FloatingButton等のView表示や画像を切り替えたりすることも可能です。
なお、今回の記事を書くに当たり下記サイトを参考にさせて頂きました。
Discussion