`context.getColor`中`theme`的用途是什么?

问题描述 投票:3回答:1

背景

从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 docstheme说不多:

enter image description here

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

我发现了什么

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

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. 支持库函数有什么用?使用已弃用的功能有何不同?
android android-resources android-theme
1个回答
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。如上所述,它们的实用性是值得商榷的。

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

© www.soinside.com 2019 - 2024. All rights reserved.