LoginSignup
1
1

More than 3 years have passed since last update.

CoordinatorLayout.Behaviorを独自実装する上での前提知識

Posted at

CoordinatorLayoutAppBarLayout を使うSampleはよく見かけますが、 CoordinatorLayout.Behavior を独自実装して制御しているサンプルはあまり見なかったので、すごくざっくりですが動かし方を書いてみようと思います。

CoordinatorLayoutとAttachedBehavior

スクロールできる DependedView と、それに伴って動く ComsumedScrollView が存在するViewがあるものとします。 AppBarLayout の代わりが ComsumedScrollView で、 xmlで layout_behavior を設定していたものが DependedView だと思ってください。この ComsumedScrollViewDependedViewCoordinatorLayout.AttachedBehavior を実装していて、 CoordinatorLayout は実装された behavior をスクロール検知時にいい感じに叩いてくれます。

<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ComsumedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <DependedView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

スクロールを奪い取るView

ConsumedScrollView.kt
class ComsumedScrollView @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr), CoordinatorLayout.AttachedBehavior {

    override fun getBehavior(): CoordinatorLayout.Behavior<*> = Behavior(context)

   class Behavior(context: Context, attrs: AttributeSet? = null) : CoordinatorLayout.Behavior<ComsumedScrollView>(context, attrs) {

        override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: ComsumedScrollView, directTargetChild: View, target: View, axes: Int, type: Int): Boolean {
            // 1
            return true
        }

        override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: ComsumedScrollView, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
            // 2
        }
    }
} 

1でtrueを返答することで、そのScrollを奪い取る可能性があることを教えます。trueを返答した場合に、2が呼び出され、ここにスクロール時にカスタマイズしたい動作を記載します。スクロールでViewを円形に動かしたりとか、ある程度進んだ後に画面上部に固定するとか、動きを実装します。もし、このViewがある一定の動きをするまで他のスクロールを止めたいというのであれば、consumedでどれだけスクロールを消費したか?を教えます。

付随して動くView

DependedView.kt
class DependedView @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null
) : ViewPager(context, attrs), CoordinatorLayout.AttachedBehavior {

    override fun getBehavior(): CoordinatorLayout.Behavior<*> = Behavior(context)

    class Behavior(context: Context, attrs: AttributeSet? = null) : CoordinatorLayout.Behavior<DependedView>(context, attrs) {

        override fun layoutDependsOn(parent: CoordinatorLayout, child: DependedView, dependency: View): Boolean {
            // 1
            return true
        }

        override fun onDependentViewChanged(parent: CoordinatorLayout, child: DependedView, dependency: View): Boolean {
            // 2
            return true
        }
    }
}

1にはスクロールによって動いたviewが通知されます。通知されたviewに付随してなにかを動かす必要がある場合は、ここでtrueを返答します。1でtrueを返答した場合に2が呼び出されます。ここで、スクロールしたやつの真下についていくとか、一緒に回転するとか独自の動きを実装します。

まとめ

AppBarLayoutの中を見るともっと詳細なことはわかると思いますが、scrollを察知して奪い取って動く側と、奪い取られた動きを元に動くやつの実装をすればいい感じに動かせるっていう大前提がわかっているとちょっとは捗るんじゃないかと思います。具体的なサンプルは時間があれば書きます。。。

1
1
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
1