在`context.getColor`中使用`theme`是什么?

时间:2017-12-24 15:56:44

标签: android android-resources android-theme

背景

从API 23开始,不推荐使用获取资源 getColor (仅提供资源ID)的小方法:

enter image description here

相反,我们被告知要使用包含Theme参数的方法:

  

此方法在API级别23中已弃用。使用getColor(int,Theme)   代替。

https://developer.android.com/reference/android/content/res/Resources.html#getColor(int,android.content.res.Resources.Theme)

问题

The docs theme

不太了解

enter image description here

https://developer.android.com/reference/android/content/res/Resources.html#getColor(int,android.content.res.Resources.Theme)

我发现了什么

通过互联网搜索,我能找到的是我们可以使用支持库来获取颜色:

ContextCompat.getColor(context, R.color.color_name);

这有点奇怪,因为在幕后,它似乎并没有像主题那样做任何事情。这是其代码:

@ColorInt
    public static final int getColor(@NonNull Context context, @ColorRes int id) {
        if (Build.VERSION.SDK_INT >= 23) {
            return context.getColor(id);
        } else {
            return context.getResources().getColor(id);
        }
    }

看看Context.getColor,我可以看到:

enter image description here

所以在我看来它使用了活动的主题?

问题

  1. '主题的目的是什么?参数?

  2. 如何使用?有没有关于它的样本/教程/文章?

  3. 为什么函数不赞成?它对我来说似乎仍然安全......

  4. 支持库功能的用途是什么?使用已弃用的功能有何不同?

2 个答案:

答案 0 :(得分:5)

<强> TL;博士

  • 如果您的min SDK为23 ,则不需要使用compat API来获取颜色。
  • 如果您不使用颜色中的主题属性引用而且不计划更改,请使用您习惯的Context.getResources().getColor(int)getColorStateList(int)。它被标记为已弃用,但在功能上它没关系。
  • 如果您只想在API 23+的颜色中使用主题属性引用,请使用ContextCompat.getColorStateList(Context, int)
  • 如果您使用AppCompat并希望能够在所有Android版本上使用主题属性参考,请使用AppCompatResources.getColorStateList(Context, int)

启动API 23 ColorStateList可以包含主题属性引用,这与自API 21以来Drawable中允许的内容相同。

主题属性主要用于通过getColorStateList方法而不是getColor获得的颜色状态列表,因此我将从现在开始使用它。所提到的大多数都适用于这两种变体。

示例:

<强> RES /颜色/ my_csl.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:color="?attr/colorControlHighlight" android:alpha="?android:disabledAlpha"/>
    <item android:color="?attr/colorControlHighlight"/>
</selector>
  

'主题'参数的目的是什么?

主题是解析主题属性所必需的。资源本身并不知道任何主题。主题由上下文提供。

context.getColorStateList(R.color.my_csl);

本质上是

的捷径
context.getResources().getColorStateList(R.color.my_csl, context.getTheme());

这两种方法都是公共API的一部分,因此它们都被反向移植:

ContextCompat.getColorStateList(context, R.color.my_csl);
ResourcesCompat.getColorStateList(context.getResources(), R.color.my_csl, context.getTheme());
  

如何使用?

通常它就像这样简单:

final int myColor = ContextCompat.getColorStateList(context, R.color.my_csl);

如果您使用AppCompat,最好选择其他选项:

final int myColor = AppCompatResources.getColorStateList(context, R.color.my_csl);

以下是这两个选项之间的比较:

  • ContextCompat.getColorStateList

    • 仅需support-compat支持库
    • 仅反向移植API - 在尝试解析API 23
    • 下的主题属性时会崩溃
  • AppCompatResources.getColorStateList

    • 需要完整的appcompat-v7支持库
    • Backports功能 - 即使在API 23下也会尊重上下文主题

ResourcesCompat.getColorStateList(int, Theme)Resources.getColorStateList(int, Theme)的API(非功能性)后端,Context.getColorStateList(int)在API 23+上内部使用。在日常使用中,您将不需要这种方法。

  

为什么函数不赞成?它对我来说似乎仍然安全......

该方法已弃用,可将开发人员从不知道主题的版本迁移到方法的主题感知版本。

主题 - 不知道方法仍然可以非常安全地使用,只要您使用它来获取没有主题属性引用的颜色,例如:

<强> RES /值/ colors.xml

<resources>
    <color name="my_cint">#f00</color>
</resources>

可以安全地获得

context.getResources().getColor(R.color.my_cint);
  

支持库功能的用途是什么?

ContextCompat.getColorStateList(context, R.color.my_csl);

就是字面意思

public static final ColorStateList getColorStateList(Context context, @ColorRes int id) {
    if (Build.VERSION.SDK_INT >= 23) {
        return context.getColorStateList(id);
    } else {
        return context.getResources().getColorStateList(id);
    }
}

该方法存在,因此您无需在任何地方编写if-else。就是这样。

在API 23+上,它可以使用上下文主题。在API 23下面,它回退到无法解析主题属性的旧版本。

ResourcesCompat.getColorStateList(int, Theme)看起来和工作方式类似,它忽略了API 23下面的主题属性(在使用时崩溃)。

AppCompatResources.getColorStateList(Context, int)不会崩溃并正确解析所有Android版本的主题属性。

  

ResourcesCompat#getColorStateList怎么样?

您通常不需要这种方法。

这是一个抽象层。它告诉你,要解决一种颜色你不需要任何神对象,任何ContextResources足以解析颜色。但是Resources能够解析您需要提供Theme的主题属性。可以从Theme获取Context的事实与Resources无关。 Resources并未透露或关注它本身来自某些Context.getResources()

  

你能[...]更新getColor吗?

getColor将解决

  • <color>资源为颜色整数
  • <selector>颜色状态列表资源为其默认颜色的颜色整数

getColorStateList将解决

  • <color>资源为ColorStateList,只有一种颜色
  • <selector> CSL资源为ColorStateList,具有指定的颜色

使用消费者API所需的那个。

没有AppCompatResources.getColor(Context, int),因为颜色资源被定义为主题属性引用几乎没有意义。如果你需要这个AppCompatResources.getColorStateList(Context, int).getDefaultColor()是功能等同的。

存在

ContextCompat.getColor(Context, int)ResourcesCompat.getColor(Resources, int, Theme),因为它们反映了框架API。如上所述,它们的实用性是值得商榷的。

我建议阅读下面的讨论,以掌握一些难以捉摸的微妙差异。

答案 1 :(得分:0)

我经常使用片段,并且通过玩耍找到了这些片段。 首先按如下所示设置上下文变量:

self.setWindowFlags(_qt.FramelessWindowHint)

然后实例化上下文,如下所示:

private lateinit var  contextX: Context

然后使用contextX将颜色分配给视图

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
contextX=requireContext() ...... 

这很好。所需的导入应由系统自动生成。

导入此功能后,应自动加载它们,但在选择提示时要小心。

binding.veeGroupId.setBackgroundColor(getColor(contextX,R.color.yellow_light))