Как установить цвет текста библиотеки закупок библиотеки для чего-то другого, кроме android: textColor?

Итак, я начал использовать новую Snackbar в библиотеке поддержки дизайна, но обнаружил, что когда вы определяете "андроид: textColor" в своей теме, это относится к цвету текста закутки. Это, очевидно, проблема, если ваш основной цвет текста темный.

enter image description here

Кто-нибудь знает способ обойти это или посоветуйте, как мне покрасить текст?

EDIT Январь 2017: (пост-ответ)

Несмотря на то, что существуют некоторые специальные решения для устранения проблемы, приведенной ниже, вероятно, полезно обеспечить правильный путь к темам Snackbars.

Во-первых, вы, вероятно, не должны определять android:textColor в своих темах вообще (если только вы не знаете, в чем смысл темы). Это устанавливает цвет текста в основном для каждого вида, который соединяется с вашей темой. Если вы хотите определить цвета текста в своих представлениях, которые не являются стандартными, используйте android:primaryTextColor и укажите этот атрибут в своих пользовательских представлениях.

Однако для применения тем к Snackbar обратитесь к этому руководству по качеству из документа стороннего материала: http://www.materialdoc.com/snackbar/ (Следуйте реализация программной темы, чтобы она не зависела от стиля xml)

Для справки:

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

(Вы также можете создать свои собственные макеты Snackbar, см. ссылку выше. Сделайте так, если этот метод слишком взломан, и вы хотите получить надежный способ обновить свой пользовательский Snackbar с помощью возможных обновлений библиотеки поддержки).

И, альтернативно, см. ответы ниже для получения похожих и, возможно, более быстрых ответов для решения вашей проблемы.

Ответ 1

Я знаю, что на этот вопрос уже был дан ответ, но самый простой способ, который я нашел, был непосредственно в make с использованием метода Html.fromHtml и тега font

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

Ответ 2

Я узнал об этом в разделе "Что нового в библиотеке поддержки дизайна Android и как использовать ее 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();



ОБНОВЛЕНИЕ: ANDROIDX: Как указывает dblackker в комментариях, с новой библиотекой поддержки AndroidX код для поиска идентификатора Snackbar TextView изменяется на:

TextView tv = snack.findViewById(com.google.android.material.R.id.snackbar_text);

Ответ 3

Создал эту функцию расширения kotlin, которую я использую в своих проектах:

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

    return this
}

Использование, как вы ожидаете:

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

Ответ 4

Хорошо, поэтому я исправил его, в основном, реорганизуя способ, которым я рисую цвета текста.

В моей легкой теме я установил android:textColorPrimary в normal dark text, я хотел, и я установил android:textColor в white.

Я обновил все свои текстовые представления и кнопки, чтобы иметь android:textColor="?android:attr/textColorPrimary".

Так как snackbar рисует от textColor, я просто устанавливаю весь свой другой текст на textColorPrimary.

ИЗМЕНИТЬ ЯНВАРЬ 2017: ---------------------------------------- ------------

Итак, как говорят комментарии, и как указано в отредактированном исходном вопросе выше, вы, вероятно, не должны определять android:textColor в своих темах, так как это изменяет цвет текста каждого вида внутри темы.

Ответ 5

Взлом на android.support.design.R.id.snackbar_text является хрупким, лучше или менее хакерским способом сделать это будет:

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

Ответ 6

Один подход заключается в использовании интервалов:

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

С пролетами вы также можете добавить несколько цветов и стилей внутри одной закуски. Вот хороший гид:

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

Ответ 7

Если вы перешли на androidX, используйте com.google.android.material.R.id.snackbar_text вместо android.support.design.R.id.snackbar_text для изменения цвета текста на панели.

Ответ 8

Единственный способ, которым я вижу, - использовать getView() и ездить по велосипеду через его дочерний элемент. Я не знаю, будет ли это работать, и это плохо, как кажется. Надеюсь, они скоро добавят API по этой проблеме.

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

Ответ 9

Если вы перенесете свой код в AndroidX, свойство TextView теперь:

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

Ответ 10

Я изменил тему

Theme.AppCompat.Light.NoActionBar

to

Theme.AppCompat.NoActionBar 

Это сработало. Попытайтесь использовать простую тему вместо легкой или другой темы.

Ответ 11

Это то, что я использую, когда мне нужны пользовательские цвета

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

И потребляется как:

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

Ответ 12

Если вы решили использовать грязное и хакерское решение для поиска TextView в Snackbar по id, и вы уже мигрировали на androidx, то вот код:

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)

Ответ 13

Вы можете использовать эту библиотеку: https://github.com/SandroMachado/restaurant

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

Отказ от ответственности: я создал библиотеку.

Ответ 14

У меня есть простой код, который поможет получить экземпляр как текстового представления Snackbar, после чего вы можете вызвать все методы, которые применимы к текстовому виду.

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

Ответ 15

Snackbar.make(getView(), "Hello", Snackbar.LENGTH_SHORT)
    .setActionTextColor(Color.WHITE)
    .show();

Ответ 16

Просто чтобы сэкономить ваше драгоценное время на разработку, вот статический метод, который я использую:

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

Вот как это выглядит:

yellow snackbar with black text

Ответ 17

Если вы находитесь в Kotlin, вы можете создать расширение:

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
}

Использование:

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

Ответ 18

Поиск по идентификатору не работает для меня, поэтому я нашел другое решение:

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

Ответ 19

Согласно новым компонентам AndroidX Jitpack

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

Используйте это расширение, которое я создал

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

Используйте это так

btn_login.snack(
        getString(R.string.fields_empty_login),
        ContextCompat.getColor([email protected], R.color.whiteColor)
    ) {
        action(getString(R.string.text_ok), ContextCompat.getColor([email protected], R.color.gray_300),ContextCompat.getColor([email protected], R.color.yellow_400)) {
            [email protected]()
        }
    }

Ответ 20

Это мой обходной путь для решения проблемы такого типа в androidx с помощью kotlin

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

Вам нужно инициализировать mContent внутри метода onViewCreated, как показано ниже

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

Ответ 21

Я также заметил ту же проблему. Благодаря ответам здесь я создал небольшой класс, который может помочь решить эту проблему более легко, просто заменив это:

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

с этим:

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

Вот мой класс:

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

}