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" ...
そういうレイアウトを作るシーンがあるかどうかは、、、わかりませんがご参考になればー。