kako.dev

開発、自作アプリのこと

ViewGroup.descendantFocusability(勝手にスクロールされるのを助けてくれるアイツ)をちょっとだけ理解する

ScrollViewが勝手にスクロールする

NestScrollViewやScrollViewなんかで以下のようなレイアウトを組んでるとき、Viewの更新のタイミングでスクロールが勝手に動いて困ることがよくあります。

<androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        android:scrollbars="vertical">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
         ...

android:descendantFocusability="blocksDescendants"で解決

手っ取り早く解決したい場合、だいたい スクロールしてしまう対象に android:descendantFocusability="blocksDescendants" を設定します。 上の例に追加するなら以下のようになりますね。

<androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        android:scrollbars="vertical">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:descendantFocusability="blocksDescendants"> <!-- ←これを追加 -->
         ...

これで勝手にスクロールしなくなりました。で終わりならいいんですが、これがなんなのか気になったので少しだけ調べてみました。(本当に少しだけ)

プロパティの内容

descendantFocusabilityはViewがフォーカスをとるときにViewGroupと子ビューの関係性を定義します。 設定できる値は以下です。

Constant Value Description
afterDescendants 1 The ViewGroup will get focus only if none of its descendants want it.
beforeDescendants 0 The ViewGroup will get focus before any of its descendants.
blocksDescendants 2 The ViewGroup will block its descendants from receiving focus.

勝手にスクロールする現象を止めるのに使用したのは、blocksDescendantsですね。

副作用

Descriptionに書いてある通り、フォーカスをブロックしちゃいます。 ただし、クリック(タップ)は反応します。

つまり、以下のような子ビューにEditTextなどがありフォーカスさせたいビューが存在する場合は、android:descendantFocusability="blocksDescendants"は使用しない方が良いです。

<androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        android:scrollbars="vertical">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:descendantFocusability="blocksDescendants">

                <EditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    ...

そういうレイアウトを作るシーンがあるかどうかは、、、わかりませんがご参考になればー。

参考

https://developer.android.com/reference/android/view/ViewGroup.html#attr_android:descendantFocusability