So I\'ve started using the new Snackbar in the Design Support Library, but I found that when you define \"android:textColor\" in your theme, it applies to the text color of the
Created this kotlin extention function i use in my projects:
fun Snackbar.setTextColor(color: Int): Snackbar {
val tv = view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
tv.setTextColor(color)
return this
}
Usage like you would expect:
Snackbar.make(view, R.string.your_string,Snackbar.LENGTH_LONG).setTextColor(Color.WHITE).show()
Currently (January 2020) with
com.google.android.material:material:1.2.0
and probably also 1.1.0
Is definitely the best way how to do it by overrides these styles:
<item name="snackbarStyle">@style/Widget.MaterialComponents.Snackbar</item>
<item name="snackbarButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Snackbar</item>
<item name="snackbarTextViewStyle">@style/Widget.MaterialComponents.Snackbar.TextView</item>
If you use a material theme with .Bridge
at the end, for some reason, neither of these styles are defined. So Snackar will use some legacy layout without these styles.
I found in the source code that both snackbarButtonStyle
and snackbarTextViewStyle
must be defined otherwise it will be not used.
As per new AndroidX Jitpack components
implementation 'com.google.android.material:material:1.0.0'
Use this extension which i had created
inline fun View.snack(message: String, length: Int = Snackbar.LENGTH_LONG,
f: Snackbar.() -> Unit) {
val snack = Snackbar.make(this, message, length)
snack.f()
snack.show()
}
fun Snackbar.action(action: String, actionColor: Int? = null, textColor: Int? = null, listener: (View) -> Unit) {
setAction(action, listener)
actionColor?.let {
setActionTextColor(it)
}
textColor?.let {
this.view.findViewById<TextView>(R.id.snackbar_text).setTextColor(it)
}
}
Use it like this
btn_login.snack(
getString(R.string.fields_empty_login),
ContextCompat.getColor(this@LoginActivity, R.color.whiteColor)
) {
action(getString(R.string.text_ok), ContextCompat.getColor(this@LoginActivity, R.color.gray_300),ContextCompat.getColor(this@LoginActivity, R.color.yellow_400)) {
this@snack.dismiss()
}
}
Alright so I fixed it by basically reorganizing the way I do text colors.
In my light theme, I set android:textColorPrimary
to the normal dark text
I wanted, and I set android:textColor
to white
.
I updated all of my text views and buttons to have android:textColor="?android:attr/textColorPrimary".
So because snackbar draws from textColor
, I just set all of my other text to textColorPrimary
.
EDIT JANUARY 2017: ----------------------------------------------------
So as the comments say, and as stated in the edited original question above, you should probably not define android:textColor
in your themes, as this changes the text color of every view inside the theme.
The only way I see is using getView()
and cycling through its child. I don't know if it's going to work, and it is bad as it looks. I hope they'll add some API about this issue soon.
Snackbar snack = Snackbar.make(...);
ViewGroup group = (ViewGroup) snack.getView();
for (int i = 0; i < group.getChildCount(); i++) {
View v = group.getChildAt(i);
if (v instanceof TextView) {
TextView t = (TextView) v;
t.setTextColor(...)
}
}
snack.show();
If you will migrate your code to AndroidX, the TextView property is now:
com.google.android.material.R.id.snackbar_text