如何将支持库的快餐栏文本颜色设置为android:textColor以外的颜色?


95

因此,我开始在设计支持库中使用新的Snackbar,但是我发现,当您在主题中定义“ android:textColor”时,它将应用于快餐栏的文本颜色。如果您的主要文字颜色为深色,这显然是一个问题。

在此处输入图片说明

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

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

虽然有一些自定义解决方案可以解决以下问题,但是最好提供正确的主题小吃店方法。

首先,您可能根本不应android:textColor在主题中进行定义(除非您真的知道使用主题的范围)。这设置了基本上每个连接到主题的视图的文本颜色。如果要在非默认视图中定义文本颜色,请android:primaryTextColor在自定义视图中使用并引用该属性。

但是,要将主题应用到Snackbar,请参考第三方材料doc上的本质量指南: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持续到可能的支持库更新,则可以这样做)。

另外,请参见下面的答案,以获取解决问题的类似且可能更快的答案。


感谢您的解决方案!该物业实际上称为android:textColorPrimary
muetzenflo

感谢您的全面解释。
错误发生

“对于您的主题,您可能根本不应该定义android:textColor ...”这对我来说很关键,谢谢!
泰勒

Answers:


41

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

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

3
我更喜欢这种解决方案,因为它是单行的。
Lahiru Chandima

1
这不是该问题的实际解决方案。用法:snackbar.setActionTextColor(Color.WHITE).show();
Ahamadullah Saikat'7

小吃栏设置中有/有错误,颜色无反应。无论如何,这种方式都有效,但对于其他人而言可能不是最佳解决方案。
JPM

这需要API级别> 24。
frank17

171

我在Android设计支持库的新功能有哪些以及如何使用其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))

2
以防万一其他人徒劳地寻找改变Snackbar文本大小的方法,就是这样!
Janis Peisenieks,2015年

2
仅供参考,您可以使用snackbar_action代替来对操作文本执行相同的操作snackbar_text。参见以下示例答案:stackoverflow.com/a/36800101/293280
Joshua Pinter

7
充其量是骇客-未来版本的支持库中android.support.design.R.id.snackbar_text的ID更改时会发生什么?是否有某种默认的SnackBar样式可以在styles.xml中覆盖?
DiscDev 2016年

7
该ID确实在支持库的将来版本中已更改,我现在得到的是空指针。
CaptainForge

3
更新-使用androidx,id现在如下:snack.view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
dblackker

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

15

创建了我在项目中使用的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(视图,R.string.your_string,Snackbar.LENGTH_LONG).setTextColor(Color.WHITE).show()


喜欢简单使用Kotlin扩展方法!;-)
Patrick Kuijpers

13
com.google.android.material.R.id.snackbar_text如果您迁移到AndroidX,请使用。
Rishabh876 '18

更改为@ Rishabh876 :)
理查德

14

好的,所以我基本上通过重新组织文本颜色的方式来解决此问题。

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

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

因此,因为快餐栏来自textColor,所以我只将所有其他文本设置为textColorPrimary

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

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


我刚刚完成了这个任务,!但是,我需要对陈旧的“首选项”活动使用以下“ m vai's”方法(使用preferences.xml)。我认为这使我应用程序的样式更加正确,基于主题,这很好。+1
OceanLife

1
IMO不是一个好的解决方案,我想保留我的实际主题用于textview,只是更改snakbar文本的颜色...
issamux

1
您根本不需要android:textColor在主题中进行定义。这是的样式属性TextView。如果您在主题中定义它,则将覆盖每个文本的颜色TextView或未Button在XML中指定其文本颜色的文本。这也恰好是快餐栏消息,通常会从其深色主题叠加层中获取颜色。
Eugen Pechanec '16

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

使用跨度,您还可以在一个Snackbar内添加几种颜色和样式。这是一个不错的指南:

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


9

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


您应获得一枚奖牌。
frank17

@ frank17,在这里的一些评论中提到了它。
CoolMind

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

6

如果要将代码迁移到AndroidX,则TextView属性现在为:

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

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

2

我改变了主题

Theme.AppCompat.Light.NoActionBar

Theme.AppCompat.NoActionBar 

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


2

如果您决定使用在id中的Snackbar中查找TextView的肮脏且hacky的解决方案,并且已经迁移到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)


1

按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

1

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

在此处输入图片说明


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

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

看起来是这样的:

黑色文本的黄色小吃店


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

和我的回答相同
理查德(Richard)

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

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
    }

0

目前(一月2020)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将使用一些没有这些样式的旧版式。

我的源代码都发现snackbarButtonStylesnackbarTextViewStyle必须另有规定将不被使用。


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

}


1
这是一个技巧,它依赖于各种支持库视图的ID是静态的。我将不惜一切代价避免这种解决方案。
DiscDev '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.