この記事は Goodpatch Advent Calender 2019 の 20日目です
Androidのアプリでたまに見かけるモダンなスクロールを作っており、
少し苦労したので、その知見を共有したいと思い書きました
やったもの
スクロールすると上にタイトルが固定表示されるような画面で、
1つの要素ではなく複数の要素で構成したい場合に以下の方法を使って実現しました。
実装方法
この実装にはレイアウトで対応するのが難しく、コードで制御するようにしました。
レイアウトの構成
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/mainAppBar"
android:layout_width="match_parent"
android:layout_height="260dp"
android:background="@color/colorWhite"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="@android:color/transparent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title="@string/mission"
app:expandedTitleMarginTop="24dp"
app:expandedTitleMarginStart="16dp"
app:collapsedTitleTextAppearance="@style/TextAppearance.Title.Collapsed"
app:expandedTitleTextAppearance="@style/TextAppearance.Title.Expanded"
>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:gravity="center_vertical|start"
android:alpha="0"
app:layout_collapseMode="pin"
app:contentInsetStartWithNavigation="0dp"
app:contentInsetStart="0dp"
app:navigationIcon="@drawable/ic_arrow_back_black_24dp"
>
</androidx.appcompat.widget.Toolbar>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/collapsingContents"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
app:layout_collapseMode="parallax"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:layout_behavior="com.package.view.HidingBehavior"
>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/button_expand_back"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_margin="16dp"
app:srcCompat="@drawable/ic_arrow_back_black_24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/mission"
android:layout_width="256dp"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="@string/vision"
android:textColor="@android:color/black"
android:layout_marginTop="8dp"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@id/button_expand_back"
app:layout_constraintStart_toStartOf="parent"
/>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:scaleType="fitEnd"
app:srcCompat="@drawable/girls_guns"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
ポイントとなるコード
binding.mainAppBar.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) {
val container = binding.collapsingContents
val toolbar = binding.toolbar
appBarLayout?.let {
if (verticalOffset == 0) {
if (state != CollapsingToolbarLayoutState.EXPANDED) {
state = CollapsingToolbarLayoutState.EXPANDED
container.alpha = 1f
toolbar.alpha = 0f
}
} else if (Math.abs(verticalOffset) >= it.totalScrollRange) {
if (state != CollapsingToolbarLayoutState.COLLAPSED) {
state = CollapsingToolbarLayoutState.COLLAPSED
container.alpha = 0f
toolbar.alpha = 1f
}
} else {
if (state == CollapsingToolbarLayoutState.COLLAPSED) {
container.alpha = 0.5f
toolbar.alpha = 0f
}
state = CollapsingToolbarLayoutState.INTERNEDIATE
}
}
}
})
private var state: CollapsingToolbarLayoutState = CollapsingToolbarLayoutState.EXPANDED
private enum class CollapsingToolbarLayoutState {
EXPANDED,
COLLAPSED,
INTERNEDIATE
}
さいごに
今回作ったコードを公開しました
気になるところがありましたら連絡お願いします
https://github.com/hayato-k/CollspanToolbarLayout