【问题标题】:Get color value programmatically when it's a reference (theme)当它是参考(主题)时以编程方式获取颜色值
【发布时间】:2013-06-21 02:04:20
【问题描述】:

考虑一下:

styles.xml

<style name="BlueTheme" parent="@android:style/Theme.Black.NoTitleBar">
    <item name="theme_color">@color/theme_color_blue</item>
</style>

attrs.xml

<attr name="theme_color" format="reference" />

color.xml

<color name="theme_color_blue">#ff0071d3</color>

所以主题颜色被主题引用。如何以编程方式获取 theme_color (参考)?通常我会使用getResources().getColor(),但在这种情况下不会使用,因为它被引用了!

【问题讨论】:

    标签: android android-resources android-theme


    【解决方案1】:

    这应该可以完成工作:

    TypedValue typedValue = new TypedValue();
    Theme theme = context.getTheme();
    theme.resolveAttribute(R.attr.theme_color, typedValue, true);
    @ColorInt int color = typedValue.data;
    

    在调用此代码之前,请确保将主题应用到您的 Activity。要么使用:

    android:theme="@style/Theme.BlueTheme"
    

    在您的清单或调用中(在调用 setContentView(int) 之前):

    setTheme(R.style.Theme_BlueTheme)
    

    onCreate().

    我已经用你的价值观对其进行了测试,效果很好。

    【讨论】:

    • 无论如何,通过您的解决方案,我得到一个 0 值颜色 (TypedValue{t=0x0/d=0x0})...我不使用可声明样式,只是对颜色的引用跨度>
    • 如果您不想将主题应用于活动,您可以使用主题 ID 创建一个ContextThemeWrapper,然后从中检索主题。
    • 此方法适用于android X(材料设计)
    • 如果theme_color 引用ColorStateList,则此方法不起作用:您可以使用this solution 获取默认颜色或使用AppCompatResources.getColorStateList(context, typedValue.resourceId) 获取ColorStateList 对象。
    • 现在内置。下面是等价的:MaterialColors.getColor(context, R.attr.colorError, Color.GRAY)
    【解决方案2】:

    添加到接受的答案,如果您使用的是 kotlin。

    @ColorInt
    fun Context.getColorFromAttr(
        @AttrRes attrColor: Int,
        typedValue: TypedValue = TypedValue(),
        resolveRefs: Boolean = true
    ): Int {
        theme.resolveAttribute(attrColor, typedValue, resolveRefs)
        return typedValue.data
    }
    

    然后在你的活动中你可以做

    textView.setTextColor(getColorFromAttr(R.attr.color))

    【讨论】:

    • oook,感谢您的“整合”。我没有使用 kotlin,但它很有趣。
    • 它使 TypedValue 对外界可见。对于颜色,您总是想解析引用声明,所以我有这个:@ColorInt fun Context.getThemeColor(@AttrRes attribute: Int) = TypedValue().let { theme.resolveAttribute(attribute, it, true); it.data }(这里的格式很差,但没关系)
    • 用法如下:val errorColor = context.getThemeColor(R.attr.colorError)
    • 更通用的方式,它也检索ColorStateList的默认值:@ColorInt fun Context.getThemeColor(@AttrRes attribute: Int) = obtainStyledAttributes(intArrayOf(attribute)).use { it.getColor(0, Color.MAGENTA) }(来自Nick Butcher
    • 终极方式,检索整个ColorStateList,即使它引用了另一个主题属性:fun Context.getThemeColor(@AttrRes attribute: Int): ColorStateList = TypedValue().let { theme.resolveAttribute(attribute, it, true); AppCompatResources.getColorStateList(this, it.resourceId) }(单色也会被包裹在ColorStateList中)。
    【解决方案3】:

    我们可以使用 Material Design 库提供的工具类:

    int color = MaterialColors.getColor(context, R.attr.theme_color, Color.BLACK)
    

    注意:Color.BLACK 是提供给 u 的属性的默认颜色

    【讨论】:

    • 最好的答案
    • 确保使用 MaterialColors 实用程序类是推荐的方式。甚至可以根据视图获得主题颜色:val primaryColor = MaterialColors.getColor(view, R.attr.colorPrimary)
    • 这应该是 2021 年现在可以接受的答案
    • 在我的情况下,例如“android.R.attr.textColorSecondary”不起作用。它只是透明的。但是没有使用默认颜色,所以我遇到了这个问题。有什么帮助吗?
    • @tzanke 检查你的风格,因为你没有声明android:textColorSecondary,而不是textColorSecondary。还要确保上下文应用了该样式
    【解决方案4】:

    这对我有用:

    int[] attrs = {R.attr.my_attribute};
    TypedArray ta = context.obtainStyledAttributes(attrs);
    int color = ta.getResourceId(0, android.R.color.black);
    ta.recycle();
    

    如果你想从中取出十六进制字符串:

    Integer.toHexString(color)
    

    【讨论】:

    • 这应该返回一个 ColorRes,而不是一个 ColorInt。
    • 我最终将它与 getColorResource(color) 一起使用,而不是调用回收。
    【解决方案5】:

    2021/January/8

    如果您想从主题属性中获取颜色,请使用以下步骤。

    创建一个变量 my_color 并将主题属性中的颜色存储为,

    val my_color = MaterialColors.getColor(<VIEWOBJECT>, R.attr.<YOUATRRIBUTENAME>)
    

    代替&lt;VIEWOBJECT&gt;,传递一个你想要使用颜色的视图对象,(在幕后它只是用来获取上下文为&lt;VIEWOBJECT&gt;.getContext(),以便它可以访问资源,即主题属性值) .代替&lt;YOURATTRIBUTENAME&gt;,使用您要访问的属性的名称

    示例 1:

    如果您想从某个活动中获取主题属性引用的颜色。 创建一个变量,该变量表示要在其上使用颜色的视图对象。 在这里,我的活动中有一个 textView,我将在 textview 变量中引用它的对象并将其传递给 getColor 方法,在幕后它将使用该对象来获取上下文,以便它可以访问主题属性值

    val textview: TextView = findViewById(R.id.mytextview)
    val my_color = MaterialColors.getColor(textView, R.attr<YOURATTRIBUTENAME>)
    

    示例 2:

    如果您想从自定义视图中的主题属性中获取颜色,那么只需使用,

    val my_color = MaterialColors.getColor(this, R.attr.<YOUATRRIBUTENAME>)
    

    自定义view里面this指的是自定义view的对象,其实就是一个view对象。

    【讨论】:

      【解决方案6】:

      将此添加到您的 build.gradle(应用程序):

      implementation 'androidx.core:core-ktx:1.1.0'
      

      并在代码中的某处添加此扩展功能:

      @ColorInt
      @SuppressLint("Recycle")
      fun Context.themeColor(
          @AttrRes themeAttrId: Int
      ): Int {
          return obtainStyledAttributes(
              intArrayOf(themeAttrId)
          ).use {
              it.getColor(0, Color.MAGENTA)
          }
      }
      

      【讨论】:

      • 我想从android.R.attr.textColorSecondary 参考中获取颜色,只有这个解决方案有效。谢谢。
      【解决方案7】:

      如果你想获得多种颜色,你可以使用:

      int[] attrs = {R.attr.customAttr, android.R.attr.textColorSecondary, 
              android.R.attr.textColorPrimaryInverse};
      Resources.Theme theme = context.getTheme();
      TypedArray ta = theme.obtainStyledAttributes(attrs);
      
      int[] colors = new int[attrs.length];
      for (int i = 0; i < attrs.length; i++) {
          colors[i] = ta.getColor(i, 0);
      }
      
      ta.recycle();
      

      【讨论】:

        【解决方案8】:

        我使用这个 kotlin 扩展

        @ColorInt
        fun Context.getColorFromAttr( @AttrRes attrColor: Int
        ): Int {
            val typedArray = theme.obtainStyledAttributes(intArrayOf(attrColor))
            val textColor = typedArray.getColor(0, 0)
            typedArray.recycle()
            return textColor
        }
        

        样本

        getColorFromAttr(android.R.attr.textColorSecondary)
        

        【讨论】:

          【解决方案9】:

          这是一个简洁的 Java 实用方法,它接受多个属性并返回一个颜色整数数组。 :)

          /**
           * @param context    Pass the activity context, not the application context
           * @param attrFields The attribute references to be resolved
           * @return int array of color values
           */
          @ColorInt
          static int[] getColorsFromAttrs(Context context, @AttrRes int... attrFields) {
              int length = attrFields.length;
              Resources.Theme theme = context.getTheme();
              TypedValue typedValue = new TypedValue();
          
              @ColorInt int[] colorValues = new int[length];
          
              for (int i = 0; i < length; ++i) {
                  @AttrRes int attr = attrFields[i];
                  theme.resolveAttribute(attr, typedValue, true);
                  colorValues[i] = typedValue.data;
              }
          
              return colorValues;
          }
          

          【讨论】:

          • Java 在这方面比 Kotlin 好?
          • @IgorGanapolsky 哦,我真的不知道。我分享了我的代码,因为我知道它会对外面的人派上用场!我不了解 Kotlin,我认为 Kotlin 不会让它表现得更好,也许代码行更少! :P
          【解决方案10】:

          对于那些正在寻找可绘制对象的参考的人,您应该在resolveRefs 中使用false

          theme.resolveAttribute(R.attr.some_drawable, typedValue, **false**);

          【讨论】:

          • 引用的变量 typedValue 是什么?
          • 什么是变量 theme.* 参考?
          【解决方案11】:

          对我来说,它只能使用 ContextCompattypedValue.resourceId

          正如这个问题中提出的:How to get a value of color attribute programmatically

          TypedValue typedValue = new TypedValue();
          getTheme().resolveAttribute(R.attr.colorControlNormal, typedValue, true);
          int color = ContextCompat.getColor(this, typedValue.resourceId)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-09-04
            • 2019-10-27
            • 1970-01-01
            • 1970-01-01
            • 2016-04-15
            • 1970-01-01
            • 2012-05-08
            • 2014-07-12
            相关资源
            最近更新 更多