LoginSignup
1
1

More than 1 year has passed since last update.

MaterialButtonのthemeとか調べたことまとめ

Posted at

MaterialButtonについ調べたことメモ。

環境 : com.google.android.material:material:1.4.0

デフォルトで当たるstyle

結論

多くのThemeの場合、@style/Widget.MaterialComponents.Button

詳しく

まずMaterialButtonのコンストラクタを見てみる。

image.png

R.attr.materialButtonStyleである。

※ちなみに、xmlからinflateした場合、引数が2つ(View(Context context, AttributeSet attrs))のコンストラクタが呼ばれます。

ではR.attr.materialButtonStyle の内容は?

→多くのThemeの場合、@style/Widget.MaterialComponents.Button

image.png

Base.V14.Theme.MaterialComponents.BridgeTheme.MaterialComponents.NoActionBarなどの親。

※ただし、ほかにも、@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flushのことなどもなくはない。

image.png

おまけ : @style/Widget.MaterialComponents.Buttonの内容

こんな感じ。

image.png

だれがrippleつきの背景を作成しているか

MaterilaButtonはrippleがデフォルトでつきます。
しかし@style/Widget.MaterialComponents.Buttonにはrippleの設定のような部分があるにもかかわらずほかのViewのthemeやstyleとして指定してもrippleがつきませんでした。
そこでMaterialButtonがどのようにrippleを作成しているか調べました。

結論

MaterilaButtonの見た目の一部の設定を担っているMaterilaButtonHelperbackgroundTintrippleColorの値を考慮しつつ背景のdrawableとしてRippleDrawableというLayerDrawableを設定している。

詳しく

MaterilaButtonHelperMaterilaButtonの見た目の一部の設定を担っている」

この辺り。MaterilaButtonのコンストラクタで、MaterilaButtonHelperにAttributeと自身を渡して、色々とセットしてもらっている。
※コメントにはbackgroundのことだけをやっている風に書いてあるけど、実際のコードをみるとelevationのこともやっているように見える?

image.png

  • MaterilaButtonHelper

backgroundTintrippleColorの値を考慮しつつ背景のdrawableとしてRippleDrawableというLayerDrawableを設定している。」

  • 先ほど呼ばれていたMaterilaButtonHelper#loadFromAttributes

  • の中で、MaterilaButtonHelper#updateBackgroundが呼ばれているが

  • その中でMaterilaButtonHelper#createBackgroundを呼びRippleDrawableを作成し、それを背景としてセットしている。

  • MaterilaButtonHelper#createBackgroundメソッド
image.png

  • 特にこの辺りでRippleDrawableを作成。
image.png

  • ちなみにrippleColorなどは、MaterilaButtonHelper#loadFromAttributesで渡されたAttributeから読み込んでいます。
image.png

<item name="rippleColor">で設定した値ですね。

ちなみに

android:backgroundを設定してしまうと、このrippleつきの自動生成背景がつけてもらえなくなります。
それはMaterilaButtonHelper#loadFromAttributesandroid:backgroundがあるときはMaterilaButtonHelper#updateBackgroundではなくMaterilaButtonHelper#setBackgroundOverwrittenが呼ばれるようになっており

image.png

MaterilaButtonHelper#setBackgroundOverwrittenではrippleの生成などは全く行わないからです。

image.png

AppCompatButtonに比べて、余分につくpaddingはどこが原因?

AppComapt系のthemeがあたったActivityにinflateするxmlのButtonとMaterial系のそれでは、同じandroid:paddingTopを設定しても実際のUI表示を確認するとMaterial系のそれの方が若干paddingが多くなってしまいます。その原因を探りました。

結論

MaterialButtonでは、MaterialButtonHelperがAttributeからpaddingを設定するときにandroid:paddingXXXandroid:insetXXXを加算した値を実際のpaddingとして使用し、@style/Widget.MaterialComponents.ButtoninsetTopinsetBottomの値はnon-zeroだから。

詳しく

MaterialButtonHelperがAttributeからpaddingを設定するときにandroid:paddingXXXandroid:insetXXXを加算した値を実際のpaddingとして使用」

MaterilaButtonHelper#loadFromAttributes のこの辺り

image.png

@style/Widget.MaterialComponents.ButtoninsetTopinsetBottomの値はnon-zero」

  • @style/Widget.MaterialComponents.ButtoninsetTopinsetBottomの値
image.png

@dimen/mtrl_btn_inset です。
※加えて、insetRightinsetBottomは0dpなこともわかると思います。

  • @dimen/mtrl_btn_inset
image.png

6dpです。

よって、MaterialButttonではデフォルトだと同じ値をandroid:paddingTopなどで指定してもAppCompatButtonよりTopとBottomのpaddingは少し大きくなってしまいます。
同じにしたいときはandroid;insetXXXをすべて0dpにする必要があります。

※ 厳密にはこれだけでは「差異の原因がandroid:insetXXXである」とは言えません(AppCompatButtonandroid:insetXXXを見ているかもしれない)が、AppCompatButtonButtonのコードにandroid:insetXXXを見ている部分はみつけられず、またMaterialButtonAppCompatButtonの子クラスですがandroid:insetXXXMaterialButtonXML attributesとして公式ドキュメントに書かれているので「AppCompatButtonandroid:insetXXXは見ていない」「差異の原因がandroid:insetXXXである」と言っていいと思います。

参考文献

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