【问题标题】:How to set support library snackbar text color to something other than android:textColor?如何将支持库小吃栏文本颜色设置为 android:textColor 以外的颜色?
【发布时间】:2015-09-12 17:12:05
【问题描述】:

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

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

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 保持可靠的方式,请这样做)。

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

【问题讨论】:

  • 感谢您的解决方案!该属性实际上称为android:textColorPrimary
  • 感谢您的全面解释。
  • “你可能根本不应该在你的主题中定义 android:textColor...”这对我来说是关键,谢谢!

标签: android android-support-library android-design-library android-snackbar snackbar


【解决方案1】:

我在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 在 cmets 中指出的那样,使用新的 AndroidX 支持库,查找 Snackbar TextView 的 ID 的代码更改为:

TextView tv = view.findViewById(com.google.android.material.R.id.snackbar_text);
tv.setTextColor(ContextCompat.getColor(requireContext(), R.color.someColor))

【讨论】:

  • 以防万一其他人徒劳地寻找改变 Snackbar 文本大小的方法,就是这样!
  • 仅供参考,您可以使用 snackbar_action 而不是 snackbar_text 对操作文本执行相同操作。例如,请参阅此答案:stackoverflow.com/a/36800101/293280
  • 这充其量只是一个 hack - 当 android.support.design.R.id.snackbar_text 的 ID 在支持库的未来版本中发生变化时会发生什么?在styles.xml中没有某种可以被覆盖的默认SnackBar样式吗?
  • 该 ID 在支持库的未来版本中确实发生了更改,我现在得到一个空指针。
  • 更新——使用androidx,id现在如下:snack.view.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
【解决方案2】:

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

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

【讨论】:

  • 我更喜欢这个解决方案,因为它是单行的。
  • 这不是该问题的实际解决方案。使用:snackbar.setActionTextColor(Color.WHITE).show();
  • 在 Snackbar 设置颜色中存在/曾经存在错误,但没有执行任何操作。这种方式无论如何都有效,但可能不是其他人的最佳解决方案。
  • 这需要 API 级别 >24。
【解决方案3】:

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

在我的轻主题中,我将android:textColorPrimary 设置为我想要的normal dark text,并将android:textColor 设置为white

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

因此,由于snackbar 来自textColor,因此我将所有其他文本设置为textColorPrimary

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

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

【讨论】:

  • 我刚刚完成了这个任务,唷,花了一点时间!但是,我需要使用下面的“m vai's”方法来处理我过时的首选项活动(使用preferences.xml)。我认为它使我的应用程序的样式更加正确地基于主题,这很好。 +1
  • IMO 不是一个好的解决方案,我想为 textview 保留我的实际主题并更改 snakbar 文本颜色...
  • 你根本不应该在你的主题中定义android:textColor。这是TextViewstyle 属性。如果你在 theme 中定义它,你会覆盖每个 TextViewButton 的文本颜色,它们没有在 XML 中指定其文本颜色。这也恰好是小吃店消息,它通常会从其深色 主题叠加层中获取颜色。
【解决方案4】:

创建了我在项目中使用的这个 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 扩展方法的简单使用! ;-)
  • 如果您迁移到 AndroidX,请使用 com.google.android.material.R.id.snackbar_text
  • 已更改 @Rishabh876 :)
【解决方案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();
    

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

    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 用于更改快餐栏上的文字颜色。

      【讨论】:

      • 你应该获得奖牌。
      • @frank17,这里有几个cmets提到过。
      【解决方案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】:

          目前(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 将使用一些没有这些样式的遗留布局。

          我在源码中发现snackbarButtonStylesnackbarTextViewStyle都必须定义,否则不会使用。

          【讨论】:

            【解决方案11】:

            使用Material Components Library中包含的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")
            }
            

            【讨论】:

            • 为什么这没有得到更多的支持?它工作得很好。
            【解决方案12】:

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

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

            免责声明:我制作了这个库。

            【讨论】:

            • 这个最好的解决方案,顺便说一句
            【解决方案13】:

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

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

            【讨论】:

              【解决方案14】:

              我改变了我的主题

              Theme.AppCompat.Light.NoActionBar
              

              Theme.AppCompat.NoActionBar 
              

              成功了。尝试使用简单的主题而不是灯光或其他主题。

              【讨论】:

                【解决方案15】:

                如果您决定使用肮脏和 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)
                

                【讨论】:

                  【解决方案16】:

                  按 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
                  

                  【讨论】:

                    【解决方案17】:

                    我有一个简单的代码可以帮助获取 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));
                    

                    【讨论】:

                      【解决方案18】:

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

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

                      看起来是这样的:

                      【讨论】:

                        【解决方案19】:

                        如果你在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()
                        

                        【讨论】:

                        • 和我的答案一样?
                        【解决方案20】:

                        根据新的 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()
                                }
                            }
                        

                        【讨论】:

                          【解决方案21】:

                          这是我在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()
                                  }
                              }
                          

                          您需要在onViewCreated 方法中初始化mContent,如下所示

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

                          【讨论】:

                            【解决方案22】:

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

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

                            }

                            【讨论】:

                            • 这是一个 hack,依赖于各种支持库视图的 id 是静态的。我会不惜一切代价避免这种解决方案。
                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2021-11-29
                            • 2015-11-10
                            • 2018-11-02
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多