Wie kann ich die Textfarbe der Snackbar der Unterstützungsbibliothek auf etwas anderes als Android einstellen: textColor?

94

Ich habe also angefangen, die neue Snackbar in der Design Support Library zu verwenden, aber ich habe festgestellt, dass die Definition von "android: textColor" in Ihrem Thema für die Textfarbe der Snackbar gilt. Dies ist offensichtlich ein Problem, wenn Ihre primäre Textfarbe dunkel ist.

Geben Sie hier die Bildbeschreibung ein

Kennt jemand einen Weg, um dies zu umgehen, oder hat er Ratschläge, wie ich meinen Text einfärben soll?

BEARBEITEN Januar 2017: (Post-Answer)

Es gibt zwar einige benutzerdefinierte Lösungen, um das unten stehende Problem zu beheben, aber es ist wahrscheinlich gut, die richtige Methode zum Thema Snackbars bereitzustellen.

Erstens sollten Sie android:textColorIhre Themen wahrscheinlich überhaupt nicht definieren (es sei denn, Sie wissen wirklich, in welchem ​​Umfang das Thema verwendet wird). Dadurch wird die Textfarbe praktisch jeder Ansicht festgelegt, die mit Ihrem Thema verbunden ist. Wenn Sie Textfarben in Ihren Ansichten definieren möchten, die nicht Standard sind, verwenden Sie android:primaryTextColordieses Attribut in Ihren benutzerdefinierten Ansichten und verweisen Sie darauf.

Informationen zum Anwenden von Themen Snackbarfinden Sie in diesem Qualitätsleitfaden aus einem Materialdokument eines Drittanbieters: http://www.materialdoc.com/snackbar/ (Befolgen Sie die Implementierung des programmatischen Themas, damit es nicht auf einem XML-Stil basiert.)

Als Referenz:

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

(Sie können auch Ihre eigenen benutzerdefinierten SnackbarLayouts erstellen, siehe den obigen Link. Tun Sie dies, wenn sich diese Methode zu hackig anfühlt und Sie eine sicher zuverlässige Möglichkeit suchen, Ihre benutzerdefinierte Snackbar durch mögliche Aktualisierungen der Support-Bibliothek dauerhaft zu erhalten.)

Alternativ finden Sie in den Antworten unten ähnliche und möglicherweise schnellere Antworten zur Lösung Ihres Problems.

Mahonster
quelle
danke für die lösung! Die Eigenschaft heißt eigentlichandroid:textColorPrimary
Muetzenflo
Vielen Dank für diese umfassende Erklärung.
Bugs passieren am
"du solltest android: textColor wahrscheinlich gar nicht in deinen themen definieren ..." das war der schlüssel für mich, danke!
Tyler

Antworten:

41

Ich weiß, dass dies bereits beantwortet wurde, aber der einfachste Weg, den ich gefunden habe, war die direkte Verwendung der Html.fromHtmlMethode und eines fontTags

Snackbar.make(view, 
       Html.fromHtml("<font color=\"#ffffff\">Tap to open</font>").show()
JPM
quelle
3
Ich bevorzuge diese Lösung, da es sich um eine einzelne Zeile handelt.
Lahiru Chandima
1
Dies ist nicht die eigentliche Lösung dieser Frage. Verwendung: snackbar.setActionTextColor (Color.WHITE) .show ();
Ahamadullah Saikat
Es gibt / gab einen Fehler in der Snackbar-Einstellung, bei der die Farbe nichts bewirkt hat. Diese Methode funktioniert unabhängig davon, ist jedoch möglicherweise nicht die optimale Lösung für andere.
JPM
Dies erfordert eine API-Stufe> 24.
Frank17
171

Ich fand dies unter Was sind die neuen Funktionen der Android Design Support Library und wie wird die Snackbar verwendet?

Dies funktionierte bei mir, um die Textfarbe in einer Snackbar zu ändern.

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



UPDATE: ANDROIDX: Wie dblackker in den Kommentaren hervorhebt, ändert sich mit der neuen AndroidX-Unterstützungsbibliothek der Code zum Ermitteln der ID von Snackbar TextView in:

TextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text);
tv.setTextColor(ContextCompat.getColor(requireContext(), R.color.someColor))
Jarod Young
quelle
2
Nur für den Fall, dass jemand vergeblich nach einer Möglichkeit sucht, die Textgröße einer Snackbar zu ändern, ist dies genau das Richtige!
Janis Peisenieks
2
Zu Ihrer Information, Sie können dasselbe mit dem Aktionstext tun, indem Sie snackbar_actionanstelle von verwenden snackbar_text. Siehe diese Antwort für ein Beispiel: stackoverflow.com/a/36800101/293280
Joshua Pinter
7
Dies ist bestenfalls ein Hack - was passiert, wenn sich die ID für android.support.design.R.id.snackbar_text in einer zukünftigen Version der Support-Bibliothek ändert? Gibt es nicht einen Standard-SnackBar-Stil, der in der Datei styles.xml überschrieben werden kann?
DiscDev
7
Diese ID wurde tatsächlich in einer zukünftigen Version der Support-Bibliothek geändert. Ich erhalte jetzt einen Nullzeiger.
CaptainForge
3
Update - mit AndroidX ist die ID jetzt wie folgt:snack.view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
Dblackker
15

Das Hacken android.support.design.R.id.snackbar_textist fragil. Ein besserer oder weniger hackiger Weg, dies zu tun, ist:

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

Erstellt diese Kotlin-Erweiterungsfunktion, die ich in meinen Projekten verwende:

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

    return this
}

Verwendung wie erwartet:

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

Richard
quelle
Ich liebe die einfache Verwendung von Kotlin-Erweiterungsmethoden! ;-)
Patrick Kuijpers
12
Verwenden com.google.android.material.R.id.snackbar_textSie diese Option, wenn Sie auf AndroidX migrieren.
Rishabh876
14

Also gut, ich habe es behoben, indem ich die Art und Weise, wie ich Textfarben mache, grundlegend neu organisiert habe.

In meinem Lichtthema stellte ich das ein android:textColorPrimary, was normal dark textich wollte, und ich stellte android:textColores ein white.

Ich habe alle meine Textansichten und Schaltflächen aktualisiert android:textColor="?android:attr/textColorPrimary".

Da die Snackbar aus zeichnet textColor, setze ich einfach meinen gesamten anderen Text auf textColorPrimary.

EDIT JANUAR 2017: ---------------------------------------------- ------ ------.

Wie in den Kommentaren angegeben und in der bearbeiteten Originalfrage oben angegeben, sollten Sie dies wahrscheinlich nicht android:textColorin Ihren Themen definieren , da dies die Textfarbe jeder Ansicht innerhalb des Themas ändert.

Mahonster
quelle
Ich habe diese Aufgabe gerade erledigt, Puh, hat eine Weile gedauert! Ich musste jedoch die unten stehende "m vai" -Methode für meine veraltete Voreinstellungsaktivität verwenden (mithilfe von settings.xml). Ich denke, das Styling meiner App ist themenbezogen viel korrekter, was sehr schön ist. +1
OceanLife
1
Keine gute Lösung IMO, ich möchte mein aktuelles Thema für die Textansicht behalten und einfach die Textfarbe der Snakbar ändern ...
issamux
1
Sie sollten android:textColorin Ihrem Thema überhaupt nicht definieren . Es ist ein Stil - Attribut TextView. Wenn Sie es in Ihrem Thema definieren , überschreiben Sie die Textfarbe aller TextViewoder Buttonohne Angabe der Textfarbe in XML. Das ist auch die Snackbar-Nachricht, die normalerweise Farbe von ihrer dunklen Themenüberlagerung nimmt .
Eugen Pechanec
12

Ein Ansatz besteht darin, Spannweiten zu verwenden:

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

Mit Spannweiten können Sie auch mehrere Farben und Stile in einer Snackbar hinzufügen. Hier ist eine nette Anleitung:

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

ulcica
quelle
9

Wenn Sie auf AndroidX migriert sind, verwenden Sie com.google.android.material.R.id.snackbar_textstatt android.support.design.R.id.snackbar_textzum Ändern der Textfarbe auf der Snackbar.

Rohit Maurya
quelle
Du verdienst eine Medaille.
Frank17
@ frank17, es wurde in mehreren Kommentaren hier erwähnt.
CoolMind
6

Der einzige Weg, den ich sehe, ist, getView()sein Kind zu benutzen und durch es zu radeln. Ich weiß nicht, ob es funktionieren wird, und es ist schlecht, wie es aussieht. Ich hoffe, dass sie bald eine API zu diesem Problem hinzufügen werden.

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

Wenn Sie Ihren Code auf AndroidX migrieren, lautet die TextView-Eigenschaft jetzt:

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

Dies ist, was ich benutze, wenn ich benutzerdefinierte Farben benötige

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

Und konsumiert als:

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

Ich habe mein Thema geändert

Theme.AppCompat.Light.NoActionBar

zu

Theme.AppCompat.NoActionBar 

Es hat funktioniert. Versuchen Sie, ein einfaches Thema anstelle von Licht oder einem anderen Thema zu verwenden.

Pavneet_Singh
quelle
2

Wenn Sie sich für die schmutzige und hackige Lösung entscheiden, TextView in der Snackbar anhand der ID zu finden, und bereits auf AndroidX migriert sind, lautet der folgende Code:

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

Sie können diese Bibliothek verwenden: https://github.com/SandroMachado/restaurant

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

Haftungsausschluss: Ich habe die Bibliothek erstellt.

Sandro Machado
quelle
1

Find by id hat bei mir nicht funktioniert, daher habe ich eine andere Lösung gefunden:

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

Verwenden Sie das Snackbarin der Materialkomponentenbibliothek enthaltene und wenden Sie das an

  • setTextColor um die Textfarbe zu definieren
  • setActionTextColorum die von der Aktion verwendete Textfarbe zu definieren. Sie können eine Farbe oder einen Farbwähler verwenden
  • setBackgroundTint um die Hintergrundfarbe der Snackbar zu definieren

Etwas wie:

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

Geben Sie hier die Bildbeschreibung ein

Gabriele Mariotti
quelle
0

Ich habe einen einfachen Code, der hilft, eine Instanz der beiden Textansichten von Snackbar zu erhalten. Danach können Sie alle Methoden aufrufen, die für eine Textansicht gelten.

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));
Summierter Jain
quelle
0

Um Ihre wertvolle Entwicklungszeit zu sparen, verwende ich folgende statische Methode:

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

So sieht es aus:

gelbe Snackbar mit schwarzem Text

Ifta
quelle
0

Wenn Sie sich in Kotlin befinden , können Sie eine Erweiterung erstellen:

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
}

Verwendung :

yourSnackBar.withTextColor(Color.WHITE).show()
Phil
quelle
gleiche Antwort wie meine 😉
Richard
0

Wie bei neuen AndroidX Jitpack-Komponenten

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

Verwenden Sie diese Erweiterung, die ich erstellt hatte

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

Verwenden Sie es so

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

Dies ist meine Problemumgehung, um diese Art von Problem bei der androidxVerwendung zu lösenkotlin

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

Sie müssen die mContentInside- onViewCreatedMethode wie unten initialisieren

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

Derzeit (Januar 2020) mit com.google.android.material:material:1.2.0und wahrscheinlich auch1.1.0

Ist definitiv der beste Weg, dies zu tun, indem diese Stile überschrieben werden:

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

Wenn Sie .Bridgeam Ende ein Materialthema mit verwenden , ist aus irgendeinem Grund keiner dieser Stile definiert. Snackar wird also ein altes Layout ohne diese Stile verwenden.

Ich habe im Quellcode festgestellt, dass beide snackbarButtonStyleund snackbarTextViewStyledefiniert werden müssen, sonst wird es nicht verwendet.

Atom
quelle
-1

Ich habe auch das gleiche Problem bemerkt. Dank der Antworten hier habe ich eine kleine Klasse erstellt, die helfen kann, dieses Problem einfacher zu lösen, indem sie diese ersetzt:

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

mit diesem:

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

Hier ist meine Klasse:

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
quelle
1
Dies ist ein Hack und setzt voraus, dass die IDs verschiedener Ansichten der Unterstützungsbibliothek statisch sind. Ich würde diese Lösung um jeden Preis vermeiden.
DiscDev