¿Cómo configurar el color del texto de la barra de bocadillos de la biblioteca de soporte en algo que no sea android: textColor?

94

Así que comencé a usar la nueva Snackbar en la Biblioteca de soporte de diseño, pero descubrí que cuando define "android: textColor" en su tema, se aplica al color del texto de la snackbar. Obviamente, esto es un problema si el color de su texto principal es oscuro.

ingrese la descripción de la imagen aquí

¿Alguien sabe cómo evitar esto o tiene algún consejo sobre cómo debo colorear mi texto?

EDITAR enero de 2017: (Post-respuesta)

Si bien existen algunas soluciones personalizadas para solucionar el problema a continuación, probablemente sea bueno proporcionar la forma correcta de tema Snackbars.

En primer lugar, probablemente no debería definir android:textColorsus temas en absoluto (a menos que realmente sepa el alcance de lo que está usando el tema). Esto establece el color del texto de básicamente todas las vistas que se conectan a su tema. Si desea definir colores de texto en sus vistas que no sean los predeterminados, utilice android:primaryTextColory haga referencia a ese atributo en sus vistas personalizadas.

Sin embargo, para aplicar temas a Snackbar, consulte esta guía de calidad de un documento de material de terceros: http://www.materialdoc.com/snackbar/ (Siga la implementación del tema programático para que no dependa de un estilo xml)

Para referencia:

// create instance
Snackbar snackbar = Snackbar.make(view, text, duration);

// set action button color
snackbar.setActionTextColor(getResources().getColor(R.color.indigo));

// get snackbar view
View snackbarView = snackbar.getView();

// change snackbar text color
int snackbarTextId = android.support.design.R.id.snackbar_text;  
TextView textView = (TextView)snackbarView.findViewById(snackbarTextId);  
textView.setTextColor(getResources().getColor(R.color.indigo));

// change snackbar background
snackbarView.setBackgroundColor(Color.MAGENTA);  

(También puede crear sus propios Snackbardiseños personalizados , consulte el enlace anterior. Hágalo si este método se siente demasiado engañoso y desea una forma segura y confiable de tener su Snackbar personalizado al final a través de posibles actualizaciones de la biblioteca de soporte).

Y, alternativamente, vea las respuestas a continuación para obtener respuestas similares y quizás más rápidas para resolver su problema.

Mahonster
fuente
gracias por la solucion! la propiedad se llama realmenteandroid:textColorPrimary
muetzenflo
Gracias por esta explicación completa.
Errores suceden
"probablemente no deberías definir android: textColor en tus temas ..." esa fue la clave para mí, ¡gracias!
Tyler

Respuestas:

41

Sé que esto ya ha sido respondido, pero la forma más fácil que encontré fue directamente en la marca usando el Html.fromHtmlmétodo y una fontetiqueta

Snackbar.make(view, 
       Html.fromHtml("<font color=\"#ffffff\">Tap to open</font>").show()
JPM
fuente
3
Prefiero esta solución porque es de una sola línea.
Lahiru Chandima
1
Ésta no es la solución real de esa pregunta. Utilice: snackbar.setActionTextColor (Color.WHITE) .show ();
Ahamadullah Saikat
Hay / hubo un error en la configuración de Snackbar, el color no hizo nada. De esta manera funciona pase lo que pase, pero puede que no sea la solución óptima para otros.
JPM
Esto requiere un nivel de API> 24.
frank17
171

Encontré esto en ¿Cuáles son las nuevas características de la Biblioteca de compatibilidad de diseño de Android y cómo usar su Snackbar?

Esto funcionó para mí para cambiar el color del texto en un Snackbar.

Snackbar snack = Snackbar.make(view, R.string.message, Snackbar.LENGTH_LONG);
View view = snack.getView();
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
snack.show();



ACTUALIZACIÓN: ANDROIDX: como señala dblackker en los comentarios, con la nueva biblioteca de soporte de AndroidX, el código para encontrar el ID de Snackbar TextView cambia a:

TextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text);
tv.setTextColor(ContextCompat.getColor(requireContext(), R.color.someColor))
Jarod Young
fuente
2
En caso de que alguien más esté buscando inútilmente una forma de cambiar el tamaño del texto de un Snackbar, ¡esta es!
Janis Peisenieks
2
Para su información, puede hacer lo mismo con el texto Acción utilizando en snackbar_actionlugar de snackbar_text. Vea esta respuesta para ver un ejemplo: stackoverflow.com/a/36800101/293280
Joshua Pinter
7
En el mejor de los casos, esto es un truco: ¿qué sucede cuando el ID de android.support.design.R.id.snackbar_text cambia en una versión futura de la biblioteca de soporte? ¿No existe algún tipo de estilo SnackBar predeterminado que se pueda anular en styles.xml?
DiscDev
7
De hecho, ese ID se cambió en una versión futura de la biblioteca de soporte, ahora obtengo un puntero nulo.
CaptainForge
3
Actualización: con androidx, la identificación ahora es la siguiente:snack.view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
dblackker
15

Hackear android.support.design.R.id.snackbar_textes frágil, una forma mejor o menos hack de hacerlo será:

String snackText = getResources().getString(YOUR_RESOURCE_ID);
SpannableStringBuilder ssb = new SpannableStringBuilder()
    .append(snackText);
ssb.setSpan(
    new ForegroundColorSpan(Color.WHITE),
    0,
    snackText.length(),
    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Snackbar.make(
        getView(),
        ssb,
        Snackbar.LENGTH_SHORT)
        .show();
Jet Zhao
fuente
15

Creé esta función de extensión de kotlin que uso en mis proyectos:

fun Snackbar.setTextColor(color: Int): Snackbar {
    val tv = view.findViewById(android.support.design.R.id.snackbar_text) as TextView
    tv.setTextColor(color)

    return this
}

Uso como es de esperar:

Snackbar.make (ver, R.string.your_string, Snackbar.LENGTH_LONG) .setTextColor (Color.WHITE) .show ()

Ricardo
fuente
¡Me encanta el uso simple de los métodos de extensión de Kotlin! ;-)
Patrick Kuijpers
12
Úselo com.google.android.material.R.id.snackbar_textsi migra a AndroidX.
Rishabh876
14

Muy bien, lo arreglé básicamente reorganizando la forma en que hago los colores del texto.

En mi tema de la luz, me puse android:textColorPrimarya la normal dark textque quería, y me puse android:textColora white.

Actualicé todas mis vistas de texto y botones para tener android:textColor="?android:attr/textColorPrimary".

Entonces, debido a que la barra de bocadillos se basa en textColor, configuré todo el resto de mi texto en textColorPrimary.

EDITAR ENERO DE 2017: ---------------------------------------------- ------

Entonces, como dicen los comentarios, y como se indica en la pregunta original editada anterior, probablemente no debería definir android:textColoren sus temas, ya que esto cambia el color del texto de cada vista dentro del tema.

Mahonster
fuente
Acabo de completar esta tarea, ¡uf! ¡Me tomó un tiempo! Sin embargo, necesitaba usar el método de "m vai" a continuación para mi actividad de Preferencias anticuada (usandoferences.xml). Creo que ha dejado el estilo de mi aplicación mucho más correctamente basado en el tema, lo cual es bueno. +1
OceanLife
1
En mi opinión, no es una buena solución, quiero mantener mi tema real para la vista de texto y simplemente cambiar el color del texto de la barra de snakbar ...
issamux
1
Se supone que no debes definir android:textColortu tema en absoluto. Es un atributo de estilo de TextView. Si lo define en su tema , anula el color del texto de cada TextViewo el Buttonque no especifica su color de texto en XML. Ese también es el mensaje de la cafetería que normalmente tomaría color de su superposición de tema oscuro .
Eugen Pechanec
12

Un enfoque es usar tramos:

final ForegroundColorSpan whiteSpan = new ForegroundColorSpan(ContextCompat.getColor(this, android.R.color.white));
SpannableStringBuilder snackbarText = new SpannableStringBuilder("Hello, I'm white!");
snackbarText.setSpan(whiteSpan, 0, snackbarText.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);

Snackbar.make(view, snackbarText, Snackbar.LENGTH_LONG)
                .show();

Con los tramos, también puede agregar varios colores y estilos dentro de una Snackbar. Aquí tienes una buena guía:

https://androidbycode.wordpress.com/2015/06/06/material-design-snackbar-using-the-design-support-library/

ulcica
fuente
9

Si ha migrado a androidX, utilice en com.google.android.material.R.id.snackbar_textlugar de android.support.design.R.id.snackbar_textcambiar el color del texto en la barra de aperitivos.

Rohit Maurya
fuente
Te mereces una medalla.
frank17
@ frank17, se mencionó en varios comentarios aquí.
CoolMind
6

La única forma que veo es usando getView()y ciclando a través de su hijo. No sé si va a funcionar, y es tan malo como parece. Espero que pronto agreguen alguna API sobre este problema.

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();
natario
fuente
6

Si va a migrar su código a AndroidX, la propiedad TextView ahora es:

com.google.android.material.R.id.snackbar_text
Matjaz Kristl
fuente
2

Esto es lo que uso cuando necesito colores personalizados.

    @NonNull
    public static Snackbar makeSnackbar(@NonNull View layout, @NonNull CharSequence  text, int duration, int backgroundColor, int textColor/*, int actionTextColor*/){
        Snackbar snackBarView = Snackbar.make(layout, text, duration);
        snackBarView.getView().setBackgroundColor(backgroundColor);
        //snackBarView.setActionTextColor(actionTextColor);
        TextView tv = (TextView) snackBarView.getView().findViewById(android.support.design.R.id.snackbar_text);
        tv.setTextColor(textColor);
        return snackBarView;
    }

Y consumido como:

CustomView.makeSnackbar(view, "Hello", Snackbar.LENGTH_LONG, Color.YELLOW,Color.CYAN).setAction("DO IT", myAction).show();
makata
fuente
2

Cambié mi tema

Theme.AppCompat.Light.NoActionBar

a

Theme.AppCompat.NoActionBar 

Funcionó Intente usar un tema simple en lugar de un tema ligero u otro.

Pavneet_Singh
fuente
2

Si decide utilizar la solución sucia y pirateada con la búsqueda de TextView en Snackbar por id y ya ha migrado a androidx, aquí está el código:

val textViewId = com.google.android.material.R.id.snackbar_text
val snackbar = Snackbar.make(view, "Text", Snackbar.LENGTH_SHORT)
val textView = snackbar.view.findViewById(textViewId) as TextView
textView.setTextColor(Color.WHITE)
Grzegorz Matyszczak
fuente
1

Puede utilizar esta biblioteca: https://github.com/SandroMachado/restaurant

new Restaurant(MainActivity.this, "Snackbar with custom text color", Snackbar.LENGTH_LONG)
    .setTextColor(Color.GREEN)
    .show();

Descargo de responsabilidad: hice la biblioteca.

Sandro Machado
fuente
1

Find by id no funcionó para mí, así que encontré otra solución:

Snackbar snackbar = Snackbar.make(view, text, duration);//just ordinary creation

ViewGroup snackbarView = (ViewGroup) snackbar.getView();
SnackbarContentLayout contentLayout = (SnackbarContentLayout) snackbarView.getChildAt(0);
TextView tvText = contentLayout.getMessageView();
tvText.setTextColor(/*your color here*/);

//set another colors, show, etc
Anrimian
fuente
1

Utilice el Snackbarincluido en la biblioteca de componentes de materiales y aplique el

Algo como:

Snackbar snackbar = Snackbar.make(view, "My custom Snackbar", Snackbar.LENGTH_LONG);        
snackbar.setTextColor(ContextCompat.getColor(this,R.color.xxxxx));
snackbar.setActionTextColor(ContextCompat.getColor(this,R.color.my_selector));
snackbar.setBackgroundTint(ContextCompat.getColor(this,R.color.xxxx));
snackbar.show();

ingrese la descripción de la imagen aquí

Gabriele Mariotti
fuente
0

Tengo un código simple que ayudará a obtener una instancia de la vista de texto de Snackbar, después de eso, puede llamar a todos los métodos que son aplicables en una vista de texto.

Snackbar snackbar = Snackbar.make( ... )    // Create Snack bar


snackbar.setActionTextColor(getResources().getColor(R.color.white));  //if you directly want to apply the color to Action Text

TextView snackbarActionTextView = (TextView) snackbar.getView().findViewById( android.support.design.R.id.snackbar_action );

snackbarActionTextView.setTextColor(Color.RED);  //This is another way of doing it

snackbarActionTextView.setTypeface(snackbarActionTextView.getTypeface(), Typeface.BOLD);

//Below Code is to modify the Text in Snack bar
TextView snackbarTextView = (TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text);
snackbarTextView.setTextSize( 16 );
snackbarTextView.setTextColor(getResources().getColor(R.color.white));
Summved Jain
fuente
0

Solo para ahorrar su valioso tiempo de desarrollo, aquí está el método estático que estoy usando:

public static void snack(View view, String message) {
    if (!TextUtils.isEmpty(message)) {
        Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT);
        snackbar.getView().setBackgroundColor(Color.YELLOW);
        TextView tv =  snackbar.getView().findViewById(android.support.design.R.id.snackbar_text); //snackbar_text
        tv.setTextColor(Color.BLACK);
        snackbar.show();
    }
}

Así es como se ve:

snackbar amarillo con texto negro

Ifta
fuente
0

Si está en Kotlin , puede crear una extensión:

fun Snackbar.withTextColor(color: Int): Snackbar {
    val tv = this.view.findViewById(android.support.design.R.id.snackbar_text) as TextView
    tv.setTextColor(color)
    return this
}

Uso :

yourSnackBar.withTextColor(Color.WHITE).show()
Phil
fuente
la misma respuesta que la mía 😉
Richard
0

Según los nuevos componentes de AndroidX Jitpack

implementation 'com.google.android.material:material:1.0.0'

Use esta extensión que había creado

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)
    }
}

Úselo así

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()
        }
    }
Manoj Perumarath
fuente
0

Esta es mi solución para resolver este tipo de problema al androidxusarkotlin

 fun showSnackBar(message: String) {
        mContent?.let {
            val snackbar = Snackbar.make(it, message, Snackbar.LENGTH_LONG)
            val snackbarView = snackbar.view
            val tv = snackbarView.findViewById<TextView>(R.id.snackbar_text)
            tv.setTextColor(Color.WHITE) //change the color of text
            tv.maxLines = 3 //specify the limit of text line
            snackbar.duration = BaseTransientBottomBar.LENGTH_SHORT //specify the duraction of text message
            snackbar.show()
        }
    }

Necesita inicializar el método mContentinterno onViewCreatedcomo a continuación

var mContent: View? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mContent = view
    }
Suraj Bahadur
fuente
0

Actualmente (enero de 2020) con com.google.android.material:material:1.2.0y probablemente también1.1.0

Definitivamente es la mejor manera de hacerlo anulando estos estilos:

<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>

Si usa un tema material con .Bridgeal final, por alguna razón, ninguno de estos estilos está definido. Entonces, Snackar usará algunos diseños heredados sin estos estilos.

Encontré en el código fuente que ambos snackbarButtonStyley snackbarTextViewStyledeben definirse, de lo contrario, no se usará.

Átomo
fuente
-1

También noté el mismo problema. Gracias a las respuestas aquí, he creado una clase pequeña, que puede ayudar a resolver este problema más fácilmente, simplemente reemplazando esto:

Snackbar.make(view, "Error", Snackbar.LENGTH_LONG).show();

con este:

Snackbar2.make(view, "Error", Snackbar.LENGTH_LONG).show();

Aquí está mi clase:

public class Snackbar2 {
static public Snackbar make(View view, int resid, int duration){
    Snackbar result = Snackbar.make(view, resid, duration);
    process(result);
    return result;
}
static public Snackbar make(View view, String text, int duration){
    Snackbar result = Snackbar.make(view, text, duration);
    process(result);
    return result;
}
static private void process(Snackbar snackbar){
    try {
        View view1= snackbar.getView();

        TextView tv = (TextView) view1.findViewById(android.support.design.R.id.snackbar_text);
        tv.setTextColor(Color.WHITE);

    }catch (Exception ex)
    {
        //inform about error
        ex.printStackTrace();
    }
}

}

Dr. Failov
fuente
1
Se trata de un truco y se basa en los ID de varias vistas de la biblioteca de soporte para ser estático. Evitaría esta solución a toda costa.
DiscDev