Применить стиль к MaterialButton программно
Я пытаюсь создать собственное представление, расширяющееся от 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
имущество. По какой-то причине цвет фона не меняется, и он имеет основной цвет Темы. Однако, если я попытаюсь применить стиль к MaterialButton
в XML это меняет цвет.
Любая идея, почему это может происходить или как я могу этого достичь?
5 ответов
Я тоже сталкиваюсь с той же проблемой. Единственный обходной путь, который я нашел, - это программно установить оттенок:
button.setBackgroundTintList(ColorStateList.valueOf(Color.RED));
С помощью
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)
Для TextButton
фона быть не должно (просто текст имеет цвет). Для цветной кнопки следует использовать стиль кнопки с заливкой по умолчанию, который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>
в теме вашего приложения.
Если вы хотите изменить свой стиль для 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)
Для более подробной информации обратитесь сюда
У меня была такая же проблема для простого варианта использования, мне нужно обновить кнопку
backgroundTint
а также
isEnabled
укажите, что я сделал: я создал собственный класс, который расширяется от 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" />