Jak ustawić kolor tekstu paska przekąsek w bibliotece wsparcia na inny niż android: textColor?

95

Zacząłem więc używać nowego Snackbar w bibliotece Design Support Library, ale odkryłem, że kiedy definiujesz „android: textColor” w swoim motywie, dotyczy to koloru tekstu paska przekąskowego. Jest to oczywiście problem, jeśli podstawowy kolor tekstu jest ciemny.

wprowadź opis obrazu tutaj

Czy ktoś wie, jak to obejść lub ma radę, jak pokolorować tekst?

EDYCJA Styczeń 2017: (Po odpowiedzi)

Chociaż istnieje kilka niestandardowych rozwiązań, które rozwiązują ten problem poniżej, prawdopodobnie dobrze jest zapewnić właściwy sposób tworzenia motywów barów przekąskowych.

Po pierwsze, prawdopodobnie nie powinieneś w ogóle definiować android:textColorw swoich motywach (chyba że naprawdę znasz zakres tego, czego używa motyw). To ustawia kolor tekstu w zasadzie każdego widoku, który łączy się z Twoim motywem. Jeśli chcesz zdefiniować kolory tekstu w widokach, które nie są domyślne, użyj android:primaryTextColortego atrybutu i odwołaj się do niego w widokach niestandardowych.

Jednak aby zastosować motywy do Snackbar, zapoznaj się z przewodnikiem dotyczącym jakości z dokumentu materiału strony trzeciej: http://www.materialdoc.com/snackbar/ (Postępuj zgodnie z implementacją motywu programowego, aby nie opierać się na stylu xml)

Na przykład:

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

(Możesz także tworzyć własne niestandardowe Snackbarukłady, zobacz powyższy link. Zrób to, jeśli ta metoda wydaje się zbyt hakerska i chcesz z pewnością niezawodny sposób, aby Twój niestandardowy Snackbar był ostatni dzięki możliwym aktualizacjom biblioteki wsparcia).

Alternatywnie, zapoznaj się z odpowiedziami poniżej, aby uzyskać podobne i być może szybsze odpowiedzi, aby rozwiązać problem.

Mahonster
źródło
dzięki za rozwiązanie! nieruchomość faktycznie nazywa sięandroid:textColorPrimary
muetzenflo
Dziękuję za to wyczerpujące wyjaśnienie.
Błędy wydarzyły się
„prawdopodobnie nie powinieneś w ogóle definiować android: textColor w swoich motywach…” to był dla mnie klucz, dziękuję!
Tyler

Odpowiedzi:

41

Wiem, że już na to odpowiedziano, ale najłatwiejszy sposób, jaki znalazłem, był bezpośrednio w marce przy użyciu Html.fromHtmlmetody i fonttagu

Snackbar.make(view, 
       Html.fromHtml("<font color=\"#ffffff\">Tap to open</font>").show()
JPM
źródło
3
Wolę to rozwiązanie, ponieważ jest to pojedyncza linia.
Lahiru Chandima
1
Nie jest to właściwe rozwiązanie tego pytania. Użyj: snackbar.setActionTextColor (Color.WHITE) .show ();
Ahamadullah Saikat
W Snackbar jest / był błąd, ustawienie koloru nic nie dało. W ten sposób działa bez względu na wszystko, ale może nie być optymalnym rozwiązaniem dla innych.
JPM
Wymaga to poziomu API> 24.
frank17
171

Znalazłem to na stronie Jakie są nowe funkcje biblioteki wsparcia projektowania Androida i jak używać jej paska przekąskowego?

Pomogło mi to w zmianie koloru tekstu w 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();



AKTUALIZACJA: ANDROIDX: Jak wskazuje dblackker w komentarzach, dzięki nowej bibliotece obsługi AndroidX kod do znalezienia identyfikatora Snackbar TextView zmienia się na:

TextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text);
tv.setTextColor(ContextCompat.getColor(requireContext(), R.color.someColor))
Jarod Young
źródło
2
Na wypadek, gdyby ktoś bezskutecznie szukał sposobu na zmianę rozmiaru tekstu w Snackbar, to jest to!
Janis Peisenieks
2
FYI, możesz zrobić to samo z tekstem akcji, używając snackbar_actionzamiast snackbar_text. Zobacz tę odpowiedź jako przykład: stackoverflow.com/a/36800101/293280
Joshua Pinter
7
To w najlepszym razie hack - co się stanie, gdy identyfikator android.support.design.R.id.snackbar_text zmieni się w przyszłej wersji biblioteki wsparcia? Czy nie ma jakiegoś domyślnego stylu SnackBar, który można zastąpić w styles.xml?
DiscDev
7
Ten identyfikator rzeczywiście został zmieniony w przyszłym wydaniu biblioteki wsparcia, teraz otrzymuję pusty wskaźnik.
CaptainForge,
3
Aktualizacja - w przypadku androidx identyfikator wygląda teraz następująco:snack.view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
dblackker
15

Hakowanie android.support.design.R.id.snackbar_textjest delikatne, lepszym lub mniej hakerskim sposobem na to będzie:

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
źródło
15

Utworzono tę funkcję rozszerzenia kotlin, której używam w moich projektach:

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
}

Sposób użycia, jakiego można się spodziewać:

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

Richard
źródło
Uwielbiam proste użycie metod rozszerzania Kotlin! ;-)
Patrick Kuijpers
13
Użyj w com.google.android.material.R.id.snackbar_textprzypadku migracji do AndroidX.
Rishabh876
Zmieniono @ Rishabh876 :)
Richard
14

W porządku, więc naprawiłem to, zasadniczo zmieniając sposób, w jaki robię kolory tekstu.

W moim lekkiego tematu, ustawić android:textColorPrimarydo normal dark textchciałam, i ustawić android:textColornawhite .

Zaktualizowałem wszystkie widoki tekstu i przyciski, aby mieć android:textColor="?android:attr/textColorPrimary".

Ponieważ pasek przekąsek czerpie z textColor, po prostu ustawiłem cały mój tekst natextColorPrimary .

EDYCJA STYCZNIA 2017: ---------------------------------------------- ------

Tak więc, jak mówią komentarze i jak stwierdzono w edytowanym oryginalnym pytaniu powyżej, prawdopodobnie nie powinieneś definiować android:textColorswoich motywów, ponieważ zmienia to kolor tekstu każdego widoku w motywie.

Mahonster
źródło
Właśnie wykonałem to zadanie, uff, zajęło mi to trochę czasu! Jednak musiałem użyć poniższej metody "m vai" dla mojej przestarzałej aktywności Preferencji (używając preferencji.xml). Myślę, że styl mojej aplikacji był znacznie bardziej poprawny, oparty na motywach, co jest miłe. +1
OceanLife
1
Nie jest to dobre rozwiązanie IMO, chcę zachować mój rzeczywisty motyw dla widoku tekstu i po prostu zmienić kolor tekstu snakbar ...
issamux
1
Nie powinieneś w ogóle definiować android:textColorswojego motywu. To atrybut styluTextView . Jeśli zdefiniujesz go w swoim motywie , nadpisujesz kolor tekstu każdego TextViewlub Buttonnie określa koloru tekstu w XML. Tak się składa, że ​​jest to również komunikat na pasku przekąskowym, który normalnie przybrałby kolor z powodu ciemnego motywu .
Eugen Pechanec
12

Jedną z metod jest użycie przęseł:

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

Dzięki rozpiętości możesz również dodać kilka kolorów i stylów w jednym Snackbar. Oto fajny przewodnik:

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

ulcica
źródło
9

Jeśli migrowałeś do androidX, użyj com.google.android.material.R.id.snackbar_textzamiast android.support.design.R.id.snackbar_textzmieniać kolor tekstu na pasku przekąskowym .

Rohit Maurya
źródło
Zasługujesz na medal.
frank17
@ frank17, wspomniano o tym w kilku komentarzach tutaj.
CoolMind
6

Jedyny sposób, w jaki widzę, to używanie getView()dziecka i poruszanie się po nim. Nie wiem, czy to zadziała, a na to wygląda. Mam nadzieję, że wkrótce dodadzą API dotyczące tego problemu.

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
źródło
6

Jeśli przeprowadzisz migrację kodu do AndroidX, właściwość TextView ma teraz postać:

com.google.android.material.R.id.snackbar_text
Matjaz Kristl
źródło
2

Tego właśnie używam, gdy potrzebuję niestandardowych kolorów

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

I spożywane jako:

CustomView.makeSnackbar(view, "Hello", Snackbar.LENGTH_LONG, Color.YELLOW,Color.CYAN).setAction("DO IT", myAction).show();
makata
źródło
2

Zmieniłem motyw

Theme.AppCompat.Light.NoActionBar

do

Theme.AppCompat.NoActionBar 

Udało się. Spróbuj użyć prostego motywu zamiast jasnego lub innego motywu.

Pavneet_Singh
źródło
2

Jeśli zdecydujesz się użyć brudnego i zhakowanego rozwiązania ze znajdowaniem TextView w Snackbar według identyfikatora i już migrowałeś do androidx, oto kod:

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
źródło
1

Możesz skorzystać z tej biblioteki: https://github.com/SandroMachado/restaurant

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

Zastrzeżenie: stworzyłem bibliotekę.

Sandro Machado
źródło
1

Funkcja Find by id nie działała, więc znalazłem inne rozwiązanie:

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
źródło
1

Użyj Snackbardołączonego do Biblioteki komponentów materiałów i zastosuj

Coś jak:

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

wprowadź opis obrazu tutaj

Gabriele Mariotti
źródło
0

Mam prosty kod, który pomoże uzyskać instancję zarówno widoku tekstu Snackbara, po czym możesz wywołać wszystkie metody, które mają zastosowanie w widoku tekstowym.

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
źródło
0

Aby zaoszczędzić Twój cenny czas na programowanie, oto metoda statyczna, której używam:

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

Tak to wygląda:

żółty snackbar z czarnym tekstem

Ifta
źródło
0

Jeśli jesteś w Kotlinie , możesz stworzyć rozszerzenie:

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
}

Zastosowanie :

yourSnackBar.withTextColor(Color.WHITE).show()
Phil
źródło
taka sama jak moja 😉
Richard
0

Zgodnie z nowymi komponentami AndroidX Jitpack

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

Użyj tego rozszerzenia, które stworzyłem

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

Użyj tego w ten sposób

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
źródło
0

To jest moje obejście, aby rozwiązać tego typu problem podczas androidxużywaniakotlin

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

Musisz zainicjować metodę mContentwewnętrzną onViewCreated, jak poniżej

var mContent: View? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mContent = view
    }
Suraj Bahadur
źródło
0

Obecnie (styczeń 2020) z com.google.android.material:material:1.2.0i prawdopodobnie również1.1.0

To zdecydowanie najlepszy sposób, jak to zrobić, zastępując te style:

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

Jeśli z .Bridgejakiegoś powodu użyjesz motywu materiałowego z na końcu, żaden z tych stylów nie zostanie zdefiniowany. Dlatego Snackar użyje jakiegoś starszego układu bez tych stylów.

Znalazłem w kodzie źródłowym, że oba snackbarButtonStylei snackbarTextViewStylemuszą być zdefiniowane, w przeciwnym razie nie będzie używane.

Atom
źródło
-1

Zauważyłem też ten sam problem. Dzięki odpowiedziom tutaj stworzyłem małą klasę, która może pomóc w rozwiązaniu tego problemu w łatwiejszy sposób, zastępując to:

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

z tym:

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

Oto moja klasa:

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
źródło
1
To jest hack i polega na tym, że identyfikatory różnych widoków bibliotek wsparcia są statyczne. Unikałbym tego rozwiązania za wszelką cenę.
DiscDev