100

所以我开始在设计支持库中使用新的 Snackbar,但是我发现当你在你的主题中定义“android:textColor”时,它适用于snackbar 的文本颜色。如果您的主要文本颜色较暗,这显然是一个问题。

在此处输入图像描述

有谁知道解决这个问题的方法或对我应该如何为文本着色有建议?

编辑 2017 年 1 月:(回答后)

虽然有一些自定义解决方案可以解决以下问题,但提供正确的 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 持续存在,请这样做)。

或者,请参阅下面的答案以获得类似且可能更快的答案来解决您的问题。

4

22 回答 22

180

我在What are the new features of Android Design Support Library and how to use its Snackbar?

这对我更改 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 的 ID 的代码更改为:

TextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text);
tv.setTextColor(ContextCompat.getColor(requireContext(), R.color.someColor))
于 2015-06-27T02:26:01.060 回答
41

我知道这已经得到了回答,但我发现的最简单的方法是直接在 make 中使用Html.fromHtml方法和font标签

Snackbar.make(view, 
       Html.fromHtml("<font color=\"#ffffff\">Tap to open</font>").show()
于 2016-05-18T20:13:36.797 回答
16

好吧,所以我通过基本上重新组织我做文本颜色的方式来修复它。

在我的轻主题中,我设置android:textColorPrimarynormal dark text我想要的,我设置android:textColorwhite.

我更新了我所有的文本视图和按钮android:textColor="?android:attr/textColorPrimary".

所以因为snackbar 从 中提取textColor,我只是将所有其他文本设置为textColorPrimary

2017 年 1 月编辑:---------------------------------------------------------- ------

因此,正如评论所说,以及上面已编辑的原始问题中所述,您可能不应该android:textColor在主题中定义,因为这会改变主题内每个视图的文本颜色。

于 2015-06-25T22:50:38.440 回答
16

创建了我在项目中使用的这个 kotlin 扩展函数:

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
}

像您期望的那样使用:

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

于 2018-01-08T08:08:19.197 回答
15

黑客攻击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();
于 2016-05-13T17:32:10.530 回答
12

一种方法是使用跨度:

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

使用 span,您还可以在一个 Snackbar 中添加多种颜色和样式。这是一个很好的指南:

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

于 2015-10-22T11:13:18.133 回答
10

如果您迁移到 androidX,请使用com.google.android.material.R.id.snackbar_text而不是 android.support.design.R.id.snackbar_text更改快餐栏上的文本颜色。

于 2019-01-17T11:17:37.513 回答
7

如果您将代码迁移到 AndroidX,TextView 属性现在是:

com.google.android.material.R.id.snackbar_text
于 2019-02-22T22:55:50.257 回答
6

我看到的唯一方法是使用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();
于 2015-06-25T22:48:03.883 回答
6

目前(2020 年 1 月)com.google.android.material:material:1.2.0并且可能还有1.1.0

通过覆盖这些样式绝对是最好的方法:

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

如果你在结尾使用了一个材质主题.Bridge,出于某种原因,这两种风格都没有被定义。所以 Snackar 将使用一些没有这些样式的遗留布局。

我在源代码中发现两者snackbarButtonStyle和都snackbarTextViewStyle必须定义,否则将不会被使用。

于 2020-01-23T22:22:40.850 回答
3

使用材料组件库Snackbar中包含的并应用

就像是:

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

在此处输入图像描述


使用Jetpack Compose,您可以自SnackbarHost定义定义自定义Snackbar

    snackbarHost = {
        // reuse default SnackbarHost to have default animation and timing handling
        SnackbarHost(it) { data ->
            Snackbar(
                snackbarData = data,
                contentColor = Yellow,
                actionColor = Red.copy(alpha = 0.9f)
            )
        }
    }

在此处输入图像描述

然后只需使用它:

scope.launch {
    scaffoldState.snackbarHostState.showSnackbar(
        message = "Snackbar text  # ${++clickCount}",
        actionLabel = "Done")
}
于 2019-10-29T11:51:49.480 回答
2

我改变了我的主题

Theme.AppCompat.Light.NoActionBar

Theme.AppCompat.NoActionBar 

它工作。尝试使用简单的主题,而不是光或其他主题。

于 2015-10-21T09:14:19.550 回答
2

你可以使用这个库:https ://github.com/SandroMachado/restaurant

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

免责声明:我制作了图书馆。

于 2015-11-28T01:04:44.707 回答
2

这就是我需要自定义颜色时使用的

    @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();
于 2016-01-10T01:18:30.983 回答
2

如果您决定使用肮脏和 hacky 的解决方案通过 id 在 Snackbar 中查找 TextView 并且您已经迁移到 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)
于 2018-12-16T17:22:01.507 回答
1

Find by id 对我不起作用,所以我找到了另一个解决方案:

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
于 2019-07-12T18:59:03.270 回答
0

我有一个简单的代码可以帮助获取 Snackbar 的 textview 的实例,之后您可以调用所有适用于 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));
于 2016-11-16T10:14:02.080 回答
0

只是为了节省您宝贵的开发时间,这里是我使用的静态方法:

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

这是它的外观:

带有黑色文本的黄色小吃店

于 2018-06-26T16:31:11.423 回答
0

如果你在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()
于 2018-07-18T14:59:20.243 回答
0

根据新的 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(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()
        }
    }
于 2019-07-16T06:05:34.810 回答
0

这是我在使用中解决此类问题的解决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
    }
于 2019-10-03T08:01:10.860 回答
-1

我也注意到了同样的问题。感谢这里的答案,我创建了一个小类,它可以帮助更轻松地解决这个问题,只需替换它:

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

}

于 2016-03-26T10:24:28.037 回答