如何根据 android(dark/light 主题)中的当前应用主题从字符串名称中获取可绘制资源 ID

How to get drawable resource id from string name base on current app theme in android (dark/light theme)

我可以使用以下方法按字符串名称获取资源 ID

fun resIdByName(): Int {
    return resources.getIdentifier("apple", "drawable", packageName)
}

但问题是我的应用程序中有 dark/light 情绪支持,此方法为黑暗情绪返回浅色图像,为浅色情绪返回深色图像。

我在互联网上搜索了很多,但只找到了一种从名称中获取资源的方法,而不是如何根据主题获取资源的方法,所以不要认为这是一个重复的问题。

简短回答:不要使用 setImageResource(Int id)。使用 getResources().getDrawable(Int id, Resources.Theme theme) 获取主题可绘制对象并使用 setImageDrawable(Drawable drawable) 代替。

说明:主题资源没有特定的 id suffix/preffix;在所有主题中都是相同的 ID,以避免破坏应用程序。主题应该事先应用,允许所有主题敏感的值被主题的版本替换。通常,视觉上下文 (activity) 包含引用,但根据 how/when 您尝试获取资源的情况,您可能会得到一个具有不同主题的资源(例如,应用程序上下文将没有主题引用),正因为如此,我们从 api 22 开始就有了 getDrawable(Int id, Resources.Theme theme) 。这就是问题的根源。当你调用 setImageDrawable(Int res) 时,imageView 执行这个块:

private void resolveUri() {
    if (mDrawable != null) {
        return;
    }
    if (getResources() == null) {
        return;
    }
    Drawable d = null;
    if (mResource != 0) {
        try {
            d = mContext.getDrawable(mResource);
        } catch (Exception e) {
            Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);
            // Don't try again.
            mResource = 0;
        }
    } else if (mUri != null) {
        d = getDrawableFromUri(mUri);
        if (d == null) {
            Log.w(LOG_TAG, "resolveUri failed on bad bitmap uri: " + mUri);
            // Don't try again.
            mUri = null;
        }
    } else {
        return;
    }
    updateDrawable(d);
}

如您所见,它使用了已弃用的 Context.getDrawable(Int id) 方法。因此,drawable 最多只能匹配上下文中的主题引用(如果有的话)。在您的小部件中,调用可能发生在其余更改发生之前。因此,请指定所需的主题,这样就没问题了。