白眼鏡のblog

新しく得た知見を備忘録的に書き連ねていく

AppBarLayout内のViewにAnimationを設定する

AppBarLayout内のViewにAnimationを設定する。

CoordinatorLayout使ってるアプリってどのくらいあるんでしょうか。 ListなどのScrollする画面でヘッダが隠れるこういった画面で割と使われている印象です。
f:id:wadada420:20190615104812g:plain:w200
このヘッダをScrollで隠すという処理自体は、簡単でレイアウトファイルに以下のような記述をしてあげるだけで実装できます。

<androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/appbar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_scrollFlags="scroll|enterAlways"
                app:layout_constraintTop_toTopOf="parent"/>

    </com.google.android.material.appbar.AppBarLayout>
   
    ...body content...

</androidx.coordinatorlayout.widget.CoordinatorLayout>

ただ、このままだと単純にscrollに合わせて上に隠れていくだけで面白くないですよね。
Scrollに合わせてAlphaAnimationとかScaleAnimationしたいって気持ちになります。

このAppBarLayout内のViewをscrollに合わせてAnimationさせる場合にはどうすればいいのかというと
CollapsingToolbarLayoutを使うことで、ある程度再現することはできます。
ただ、Scale位置を調整したい、Alpha値を微調整したい、移動させたいといったことをしようとするとXMLだけの設定では不可能です(知らないだけかもしれませんが…)

Scrollに合わせてAnimationをかけたい、ということなので

  • Scrollする予定の距離
  • 現在のscroll位置
  • Animationの初期値
  • Animationの目標値

をうまいことコネコネしてスクロール判定が走るたびに現在のScroll位置に対するViewを計算して描画してあげればいいわけです。 まずは、Scrollする予定の距離の取得
ここでは、タイトルを表示しているToolBar部分をscroll可能範囲とします。

val toolBarHeight = findViewById<View>(R.id.toolbar).height

Scroll位置の取得ですがAppBarLayoutのOnOffsetChangedListenerを利用します。

OnOffsetChangedListener { appBarLayout, verticalOffset ->
     when (verticalOffset) {
           0 -> {
                    // ToolBarが全て表示されている状態
                }
           toolBarHeight -> {
                    // ToolBarが全て閉じられている状態
            }
            else -> {
                    // Scroll中
            }
    }

これで、Scrollの位置を確認できるようになりました。 あとはここで取得した値に合わせて変化するようDuration=0, Duration=0, fillDuration=0, fillAfter=trueのAnimationを毎回設定するだけです。
ただ、毎回使うときにこんなことを書くのも面倒なのでライブラリ化しました。

導入するとこんな形で使えます。

https://github.com/rwadada/AnimateAppBarLayout/raw/master/art/sample.gif

面倒だなと感じる方は導入していただけると多少楽にAnimationを設定できるかもしれません。 READMEに使い方は書いてます。

github.com

以上、初めて作ってみたライブラリの宣伝でした。