レイアウトパラメータってStyleに書いていいの?

はじめに

StyleはViewの外観を指定する属性(attribute)の集まりです。
そのため、Viewの属性の共通化したい時に使っていると思います。

ただ最近「レイアウトパラメータってStyleに書いていいのかなぁ」と疑問に思うことがありました。

※ レイアウトパラメータと言っているのは、ViewのXMLに記述する android:layout_... から始まる属性のことです

<style name="Widget.AppTheme.Button.Green">
    <item name="android:layout_width">wrap_content</item>  // 書いていいの?
    <item name="android:layout_height">wrap_content</item> // 書いていいの?
    <item name="backgroundTint">@color/background_tint_green</item>
    <item name="android:textColor">@android:color/white</item>
</style>

もちろん書くのは問題ないし、同じレイアウトパラメータを書く手間も減ります。
でもこの記事を読んでから疑問に思うようになりました。

medium.com

気になった点

A style is a collection of view attribute values. https://medium.com/androiddevelopers/android-styling-themes-vs-styles-ebe05f917578

日本語訳すると「StyleはViewの属性の集まり」なので、これまでのStyleの説明と何ら変わらない気がします。
しかし view attribute valuesViewのXML attributesに定義されているものを指しているのかなと思いました。

そのように考えるとレイアウトパラメータの android:layout_widthandroid:layout_heightViewのXML attributesには定義されていないので、Styleに書く対象ではないと考えることもできます。

ちなみに android:layout_widthandroid:layout_heightViewGroup.LayoutParamsのXML attributesに定義されています。
そのため android:layout_widthandroid:layout_height はViewの属性というより、ViewGroup.LayoutParamsの属性といった方がより正確かもしれません。

どうするべきか

StyleにLayoutParamsを書くことは問題ありません。
ただ意識すべきことが2点あると思います。

  1. ViewのXMLに書いた android:layout_... の値をチェックしてLayoutParamsを決定するのは親のレイアウトであること(参考:レイアウト | Android Developers
  2. ViewGroup.LayoutParamsを継承するレイアウトごとの属性があること

1.について

ViewはLayoutParamsを持っていますが、どんなLayoutParamsがセットされるかは親のレイアウトによって変わります。
レイアウトパラメータの説明画像を見てもわかるように、親のレイアウトが LinearLayout なら LinearLayout.LayoutParams がセットされるし、親のレイアウトが ConstraintLayout なら ConstraintLayout.LayoutParams がセットされます。

2.について

例えば FrameLayout.LayoutParams には android:layout_gravity の属性がありますが、 RelativeLayout.LayoutParams にはありません。

方針案

主に「2. ViewGroup.LayoutParamsを継承するレイアウトごとの属性があること」によって、レイアウトパラメータをStyleに書くべきではないと思っています。
例えば android:layout_gravityFrameLayout 内では有効な属性ですが、 RelativeLayout 内では無効な属性になってしまいます。
また、言い換えるとStyleにレイアウトパラメータを書くということは、使用できる親のレイアウトを制限していると言えるかもしれません。
そのため、複数の種類のレイアウトで使う想定があるなら、レイアウトパラメータをStyleに書くべきではないと思っています。
(一方で、レイアウトの種類ごとにStyleを作るという方針もありかもしれません)

まとめ

  • android:layout_... から始まるレイアウトパラメータは、親のレイアウトによって有効な属性が違う
  • 複数の種類のレイアウトで一つのStyleを使うなら、レイアウトパラメータをStyleに書かない方が良さそう