【问题标题】:Apply Style to MaterialButton programmatically以编程方式将样式应用于 MaterialButton
【发布时间】:2019-02-23 09:12:04
【问题描述】:

我正在尝试创建一个从 MaterialButton 扩展的自定义视图并在代码中应用样式,因此我不需要在 xml 中执行此操作。

class CustomRedButton @JvmOverloads constructor(
    context: Context, 
    attrs: AttributeSet? = null, 
    defStyleAttr: Int = 0
) : MaterialButton(ContextThemeWrapper(context, R.style.ButtonRedStyle), attrs, defStyleAttr) 

样式是:

<style name="ButtonRedStyle" 
    parent="Widget.MaterialComponents.Button.TextButton">
    <item name="backgroundTint">@color/red</item>
    <item name="rippleColor">@color/grey</item>
    <item name="strokeWidth">1dp</item>
    <item name="strokeColor">@color/black</item>
</style>

一切正常,但 backgroundTint 属性。由于某种原因,背景颜色没有改变,它具有主题的原色。但是,如果我尝试将样式应用于 xml 中的 MaterialButton,它确实会改变颜色。

知道为什么会发生这种情况或如何实现吗?

【问题讨论】:

  • 您使用的是哪个AppTheme?如果是AppCompat 主题,请尝试将其更改为MaterialComponents 一次。
  • 我正在使用Theme.MaterialComponents.Light.NoActionBar

标签: android android-button android-theme android-styles material-components-android


【解决方案1】:

使用

MaterialButton(ContextThemeWrapper(context, R.style.ButtonRedStyle), attrs, defStyleAttr)

您将 themeoverlay 应用到默认样式,您没有应用不同的样式。

意思是:

<style name="ButtonRedTheme" parent="...">
    <item name="colorPrimary">@color/...</item>
    <item name="colorOnPrimary">@color/...</item>
    <item name="colorSecondary">@color/...</item>
</style>

如果您想应用不同的样式,您必须:

  • attrs.xml 中定义自定义属性
    <attr name="myButtonStyle" format="reference"/>
  • 在您的应用主题中为该属性分配样式:
   <style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
        <item name="myButtonStyle">@style/CustomButtonStyle</item>
   </style>
  • 定义自定义样式:
    <style name="CustomButtonStyle" parent="Widget.MaterialComponents.Button.*">
        <item name="backgroundTint">@color/...</item>
        <item name="rippleColor">@color/grey</item>
        <item name="strokeWidth">1dp</item>
        <item name="strokeColor">@color/black</item>
    </style>

最后使用:

val customButton = MaterialButton(context, null, R.attr.myButtonStyle)

【讨论】:

    【解决方案2】:

    我也面临同样的问题。到目前为止,我发现的唯一解决方法是以编程方式设置色调:

    button.setBackgroundTintList(ColorStateList.valueOf(Color.RED));
    

    【讨论】:

    • 是的,我最终也这样做了。不是最好的方法,但它确实有效。
    • 这不是“以编程方式将样式应用于 MaterialButton”问题的正确答案,设置一个 backtuondTintList 这是一个 hack。这应该是正确答案stackoverflow.com/a/63221217/1944237
    【解决方案3】:

    如果您想更改 CustomView 的样式,则必须将其传递给构造函数,方法是将其传递给第三个参数 defStyleAttr,如下所示:

    class CustomRedButton @JvmOverloads constructor(
        context: Context, 
        attrs: AttributeSet? = null, 
        defStyleAttr: Int = R.style.ButtonRedStyle // Just default style like this
    ) : MaterialButton(context, attrs, defStyleAttr)
    

    您可以像这样以编程方式初始化它,

    CustomRedButton(this, null, R.style.ButtonRedStyle) // Initialization, ('this' is context)
    

    更多详情请咨询here

    【讨论】:

    • 由于某种原因,这不适用于 MaterialButtons。没有使用样式中的任何参数。为了使它工作,我需要使用ContextThemeWrapper
    • 第三个属性是应用主题中定义的样式属性,不是样式。
    【解决方案4】:

    对于TextButton,不应该有背景(只是文本有颜色)。对于彩色按钮,您应该使用默认的 Filled Button 样式,即Widget.MaterialComponents.Button

    当作为主题应用时,按钮使用不同的属性。它在 Themed Attribute Mapping 部分中有描述:https://material.io/develop/android/components/material-button/

    Filled button
    +------------------------+-----------------------------------------+
    | Component Attribute    | Default Theme Attribute Value           |
    +------------------------+-----------------------------------------+
    | android:textAppearance | textAppearanceButton                    |
    | android:textColor      | colorOnPrimary                          |
    | iconTint               | colorOnPrimary                          |
    | rippleColor            | colorOnPrimary at 32% opacity (pressed) |
    | iconTint               | colorOnPrimary                          |
    | backgroundTint         | colorPrimary                            |
    | ...                    | ...                                     |
    +------------------------+-----------------------------------------+
    

    在您的情况下,主题应该类似于:

    <style name="ButtonRedTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
        <item name="colorPrimary">@color/red</item>
        <item name="colorOnPrimary">@color/white</item>
        <item name="colorOnSurface">@color/black</item>
    </style>
    

    您还可以将所有按钮更改为特定样式

    <item name="materialButtonStyle">@style/ButtonRedTheme</item>
    

    在您的应用主题中。

    【讨论】:

      猜你喜欢
      • 2020-06-20
      • 2019-02-06
      • 2012-12-04
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      • 2021-10-04
      相关资源
      最近更新 更多