16

我正在尝试创建一个自定义视图,从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财产。由于某种原因,背景颜色没有改变,它具有主题的原色。但是,如果我尝试将样式应用到MaterialButtonxml 中,它确实会改变颜色。

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

4

5 回答 5

11

使用

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

您正在将主题叠加应用到默认样式,您没有应用不同的样式。

它的意思是:

<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)
于 2020-08-02T21:29:34.247 回答
8

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

button.setBackgroundTintList(ColorStateList.valueOf(Color.RED));
于 2018-10-12T14:54:06.543 回答
2

如果你想改变你的风格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)

有关更多详细信息,请参阅此处

于 2018-09-19T09:11:43.673 回答
2

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

当作为主题应用时,按钮使用不同的属性。它在此处的主题属性映射部分中进行了描述: 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>

在您的应用主题中。

于 2019-10-09T09:08:39.297 回答
0

对于一个简单的用例,我遇到了同样的问题,我需要更新按钮backgroundTintisEnabled说明我做了什么:我创建了一个从 MaterialButton 扩展的自定义类

class MyCustomMaterialButton @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : MaterialButton(context, attrs)

然后我向这个类添加了一个扩展来更新按钮样式属性:

fun MyCustomMaterialButton.updateEnabledState(enabled: Boolean){
    apply {
        if(enabled){
            isEnabled = true
            setBackgroundColor(ContextCompat.getColor(context, R.color.primary))
        }
        else{
            isEnabled = false
            setBackgroundColor(ContextCompat.getColor(context, R.color.primary_warm_grey_five))
        }
    }
}

这是它在 Xml 中的样子:

   <com.karny.branding.KarnyMaterialButton
        android:id="@+id/smsAuthButton"
        style="@style/PrimaryButtonDisabled"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="94dp"
        android:layout_marginBottom="24dp"
        android:text="@string/sms_auth_check"
        app:layout_constraintEnd_toStartOf="@+id/left_middle_guide_line"
        app:layout_constraintStart_toEndOf="@+id/right_middle_guide_line"
        app:layout_constraintTop_toBottomOf="@+id/smsAuthNumberContainer" />
于 2022-02-04T14:31:37.060 回答