Come impostare il colore del testo della snackbar della libreria di supporto su qualcosa di diverso da Android: textColor?


94

Quindi ho iniziato a utilizzare la nuova Snackbar nella libreria di supporto alla progettazione, ma ho scoperto che quando definisci "android: textColor" nel tuo tema, si applica al colore del testo della snackbar. Questo è ovviamente un problema se il colore del testo principale è scuro.

inserisci qui la descrizione dell'immagine

Qualcuno sa come aggirare questo o ha consigli su come dovrei colorare il mio testo?

EDIT gennaio 2017: (post-risposta)

Sebbene ci siano alcune soluzioni personalizzate per risolvere il problema di seguito, è probabilmente utile fornire il modo corretto per temi Snackbars.

In primo luogo, probabilmente non dovresti definire affatto i android:textColortuoi temi (a meno che tu non conosca veramente l'ambito di ciò che sta usando il tema). Questo imposta il colore del testo praticamente di ogni vista che si collega al tuo tema. Se desideri definire colori del testo nelle visualizzazioni che non sono predefinite, utilizza android:primaryTextColore fai riferimento a tale attributo nelle visualizzazioni personalizzate.

Tuttavia, per applicare temi a Snackbar, fare riferimento a questa guida alla qualità da un documento di materiale di terze parti: http://www.materialdoc.com/snackbar/ (seguire l'implementazione del tema programmatico per non fare affidamento su uno stile xml)

Per riferimento:

// 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);  

(Puoi anche creare i tuoi Snackbarlayout personalizzati , vedi il link sopra. Fallo se questo metodo sembra troppo hacker e vuoi un modo sicuramente affidabile per far durare il tuo Snackbar personalizzato attraverso eventuali aggiornamenti della libreria di supporto).

In alternativa, vedi le risposte di seguito per risposte simili e forse più veloci per risolvere il tuo problema.


grazie per la soluzione! la proprietà si chiama effettivamenteandroid:textColorPrimary
muetzenflo

Grazie per questa esauriente spiegazione.
bug si verificano il

"probabilmente non dovresti assolutamente definire android: textColor nei tuoi temi ..." questa è stata la chiave per me, grazie!
Tyler

Risposte:


41

So che è già stata data una risposta, ma il modo più semplice che ho trovato è stato direttamente nel make utilizzando il Html.fromHtmlmetodo e un fonttag

Snackbar.make(view, 
       Html.fromHtml("<font color=\"#ffffff\">Tap to open</font>").show()

3
Preferisco questa soluzione poiché è a riga singola.
Lahiru Chandima

1
Questa non è la vera soluzione di questa domanda. Usa: snackbar.setActionTextColor (Color.WHITE) .show ();
Ahamadullah Saikat

C'è / c'era un bug nell'impostazione Snackbar il colore non ha fatto nulla. In questo modo funziona qualunque cosa, ma potrebbe non essere la soluzione ottimale per gli altri.
JPM

Ciò richiede un livello API> 24.
frank17

171

Ho trovato questo su Quali sono le nuove funzionalità di Android Design Support Library e come utilizzare la sua Snackbar?

Questo ha funzionato per me per cambiare il colore del testo in uno 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();



AGGIORNAMENTO: ANDROIDX: come sottolinea dblackker nei commenti, con la nuova libreria di supporto AndroidX, il codice per trovare l'ID di Snackbar TextView cambia in:

TextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text);
tv.setTextColor(ContextCompat.getColor(requireContext(), R.color.someColor))

2
Nel caso in cui qualcun altro stia cercando inutilmente un modo per cambiare la dimensione del testo di uno snackbar, questo è tutto!
Janis Peisenieks

2
Cordiali saluti, puoi fare lo stesso con il testo dell'azione usando snackbar_actioninvece di snackbar_text. Vedi questa risposta per un esempio: stackoverflow.com/a/36800101/293280
Joshua Pinter,

7
Questo è nella migliore delle ipotesi un hack: cosa succede quando l'ID per android.support.design.R.id.snackbar_text cambia in una versione futura della libreria di supporto? Non esiste un qualche tipo di stile SnackBar predefinito che può essere sovrascritto in styles.xml?
DiscDev

7
Quell'ID è stato effettivamente modificato in una versione futura della libreria di supporto, ora ricevo un puntatore nullo.
CaptainForge

3
Aggiornamento: con androidx, l'id è ora il seguente:snack.view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
dblackker

15

L'hacking android.support.design.R.id.snackbar_textè fragile, un modo migliore o meno hacker per farlo sarà:

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();

15

Ho creato questa funzione di estensione kotlin che uso nei miei progetti:

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

    return this
}

Utilizzo come ti aspetteresti:

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


Adoro il semplice utilizzo dei metodi di estensione di Kotlin! ;-)
Patrick Kuijpers

12
Da utilizzare com.google.android.material.R.id.snackbar_textse esegui la migrazione ad AndroidX.
Rishabh876

14

Va bene, quindi l'ho risolto sostanzialmente riorganizzando il modo in cui faccio i colori del testo.

Nel mio tema chiaro, ho impostato android:textColorPrimarysu quello normal dark textche volevo e ho impostato android:textColorsu white.

Ho aggiornato tutte le mie visualizzazioni di testo e pulsanti per avere android:textColor="?android:attr/textColorPrimary".

Quindi, poiché snackbar attinge da textColor, ho impostato tutto il mio altro testo su textColorPrimary.

EDIT GENNAIO 2017: ---------------------------------------------- ------

Quindi, come dicono i commenti, e come indicato nella domanda originale modificata sopra, probabilmente non dovresti definire android:textColornei tuoi temi, poiché questo cambia il colore del testo di ogni vista all'interno del tema.


Ho appena completato questo compito, ci è voluto un po '! Tuttavia, avevo bisogno di utilizzare il metodo "m vai" di seguito per la mia attività antiquata relativa alle preferenze (utilizzando le preferenze.xml). Penso che abbia lasciato lo stile della mia app molto più correttamente basato sul tema, il che è bello. +1
OceanLife

1
Non è una buona soluzione IMO, voglio mantenere il mio tema attuale per la visualizzazione del testo e cambiare solo il colore del testo della snakbar ...
issamux

1
Non dovresti affatto definire android:textColornel tuo tema. È un attributo di stile di TextView. Se lo definisci nel tuo tema , sovrascrivi il colore del testo di ogni TextViewo Buttonche non specifica il suo colore del testo in XML. Questo è anche il messaggio della snackbar che normalmente prenderebbe colore dalla sua sovrapposizione a tema scuro .
Eugen Pechanec

12

Un approccio consiste nell'utilizzare gli intervalli:

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 le campate puoi anche aggiungere diversi colori e stili all'interno di uno Snackbar. Ecco una bella guida:

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


9

Se hai migrato ad androidX, usa com.google.android.material.R.id.snackbar_textinvece di android.support.design.R.id.snackbar_textcambiare il colore del testo su snackbar.


Ti meriti una medaglia.
frank17

@ frank17, è stato menzionato in diversi commenti qui.
CoolMind

6

L'unico modo che vedo è usare getView()e scorrere suo figlio. Non so se funzionerà, ed è brutto come sembra. Spero che aggiungano presto alcune API su questo 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();

6

Se migrerai il tuo codice su AndroidX, la proprietà TextView è ora:

com.google.android.material.R.id.snackbar_text

2

Questo è quello che uso quando ho bisogno di colori personalizzati

    @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;
    }

E consumato come:

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

2

Ho cambiato il mio tema

Theme.AppCompat.Light.NoActionBar

per

Theme.AppCompat.NoActionBar 

Ha funzionato Prova a usare un tema semplice invece di luce o un altro tema.


2

Se decidi di utilizzare la soluzione sporca e hacky con la ricerca di TextView in Snackbar per id e sei già migrato ad androidx, ecco il codice:

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)


1

Trova per ID non ha funzionato per me, quindi ho trovato un'altra soluzione:

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

1

Utilizzare il Snackbarincluso nella libreria dei componenti dei materiali e applicare il

Qualcosa di simile a:

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();

inserisci qui la descrizione dell'immagine


0

Ho un semplice codice che ti aiuterà a ottenere un'istanza sia della textview di Snackbar, dopodiché puoi chiamare tutti i metodi applicabili su una textview.

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

0

Solo per risparmiare il tuo prezioso tempo di sviluppo, ecco il metodo statico che sto 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();
    }
}

Ecco come appare:

snackbar giallo con testo nero


0

Se sei in Kotlin , puoi creare un'estensione:

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
}

Utilizzo :

yourSnackBar.withTextColor(Color.WHITE).show()

stessa risposta della mia 😉
Richard

0

Come per i nuovi componenti Jitpack AndroidX

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

Usa questa estensione che avevo creato

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

Usalo in questo modo

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

0

Questa è la mia soluzione alternativa per risolvere questo tipo di problema androidxnell'utilizzokotlin

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

È necessario inizializzare il metodo mContentinterno onViewCreatedcome di seguito

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

0

Attualmente (gennaio 2020) con com.google.android.material:material:1.2.0e probabilmente anche1.1.0

È sicuramente il modo migliore per farlo sovrascrive questi stili:

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

Se usi un tema materiale con .Bridgealla fine, per qualche motivo, nessuno di questi stili è definito. Quindi Snackar utilizzerà alcuni layout legacy senza questi stili.

Ho trovato nel codice sorgente che entrambi snackbarButtonStylee snackbarTextViewStyledevono essere definiti altrimenti non verranno utilizzati.


-1

Ho notato anche lo stesso problema. Grazie alle risposte qui ho creato una piccola classe, che può aiutare a risolvere questo problema più facilmente, semplicemente sostituendo questo:

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

con questo:

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

Ecco la mia classe:

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

}


1
Questo è un trucco e si basa sugli ID di varie visualizzazioni della libreria di supporto per essere statici. Eviterei questa soluzione a tutti i costi.
DiscDev
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.