【レイアウトXML】ViewGroup in ScrollViewでlayout_gravityを設定する時の注意
結論
重要な議論は用意してないため、最初に結論から失礼します。
ScrollViewの子ViewGroup(ConstraintLayoutやLinearLayoutなど...)にて中央揃えをする場合に、 layout_gravity="center_vertical"
か"center"
を設定するのは良くないです。
もう少し正確には...
ScrollViewのスクロール方向と同じ成分が含まれるcenter系のlayout_gravity
を、子ViewGroupに指定するのは良くないです。(この場合はcenter_vertical
かcenter
)
すると、スタート位置が見切れて末尾に余計なマージンが入ってしまいます。要はレイアウト崩れます。
[補足] HorizontalScrollViewの場合
こちらは水平方向にスクロールするので、子ViewGroupに layout_gravity="center_horizontal"
か"center"
を設定すると同じことが起きます。
解決案
- ScrollViewの子ViewGroupが中央揃えをしたい場合は
layout_gravity="center_horizontal"
を使う- ただし水平方向にしか揃えられない
- もし何かを垂直方向に揃えたい場合、さらに子Viewや子ViewGroupで、gravityを設定してあげるしかない
そもそもレイアウトXMLはオワコン?説もあるので、Jetpack Composeに乗り換えていきたいですね!(自戒も込めて)
ちなみに...Stack Overflowでは意見が様々だった
同じ現象と思われる方の投稿を見つけたのですが、回答された方々の対処法がバラバラで、いまいち信憑性がありませんでした。
(android:fillViewport="true"
設定しろ、と答えてるのもあって、試したけどそれじゃ解決したなかったり...)
具体例
以降はこの事象を発見した経緯とともに説明です。
上記内容で理解された方には特に不要かと思われます。
垂直にスクロールしたい画面
次のように垂直にスクロールしたい画面があるとします(この例では、アルファベットAからZまで整列しているだけです)。
先頭 | 末尾 |
---|---|
上の例の場合、レイアウトはこんな感じです↓。
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ABC\n\n\nDEF\n\n\nGHI\n\n\nJKL\n\n\nMNO\n\n\nPQR\n\n\nSTU\n\n\nVWX\n\n\nYZ"
android:textSize="80sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
子を中央揃えしたい
Viewを中央揃えしたいときって頻繁にあるかと思います。
そんな時、ScrollViewの子にあたるViewGroup(この例ならConstraintLayout)にて、安易に
layout_gravity="center"
を設定してしまうとスクロール位置がおかしくなります。(layout_gravity="center_vertical"
も同様)
↓下の画像参照。スタート位置がAからのはずなのに見切れて、Zの下には空白入れてないのに末尾に余計なマージン(ちょうど見切れた先頭の高さ分くらい)が入っている。
先頭 | 末尾 |
---|---|
正しく中央揃えする
ScrollViewの子、ConstraintLayoutにこう書けば、水平方向に中央揃えできました!
layout_gravity="center_horizontal"
先頭 | 末尾 |
---|---|
終わりに
特に難しいことはなかったかと思います。
深く考えずに要らない方向にまでlayout_gravity
を設定してしまうと、今回ご紹介させていただたような問題に遭遇することがあります。
今回の現象の原因は未調査
なんとなく、ScrollViewと子ViewGroupの要素の高さ計算のタイミングなどによるものだと想像してます。
なので逆に、コード上で描画の適切なタイミングでlayout_gravity
とか設定してあげれば、今回NGだと書いたlayout_gravity="center"
な実装も可能なのかな〜とか、思ってます。
これを深掘りするなら、その分をJetpack Composeの勉強に充てたいという素直な気持ちもありますし。。
拙い解説でしたが最後まで見ていただきありがとうございました!
今回ご紹介した内容が、AndroidでレイアウトXMLを書いてる方に届けばとても嬉しいです!
Discussion