You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检查Android Drawable资源是否存在夜间模式变体?

如何检查Android Drawable资源是否存在夜间模式变体?

嘿,这个场景我太熟悉了——用Glide加载资源时碰到主题切换的缓存问题,还要被迫存两份其实没必要的Drawable,确实挺糟心的。其实咱们可以先判断目标Drawable有没有对应的夜间模式变体,再决定要不要给Glide加区分明暗的签名,这样就能避免缓存冗余啦。

下面给你两种实用的检查方法,结合你的Glide场景来用:

方法一:通过资源标识符查找夜间变体

Android的夜间模式资源一般会放在带night限定符的目录(比如drawable-night),我们可以利用Resources.getIdentifier()来定位对应的资源是否存在:

fun hasNightModeDrawable(context: Context, drawableResId: Int): Boolean {
    val resources = context.resources
    // 获取原资源的名称、类型和包名
    val resName = resources.getResourceEntryName(drawableResId)
    val resType = resources.getResourceTypeName(drawableResId)
    val resPackage = resources.getResourcePackageName(drawableResId)

    // 构造夜间模式的配置,用来查找对应变体
    val nightConfig = Configuration().apply {
        uiMode = Configuration.UI_MODE_NIGHT_YES
    }
    // 尝试获取夜间模式下的资源ID
    val nightResId = resources.getIdentifier(resName, resType, resPackage, nightConfig)
    
    // 返回是否找到有效资源(非0即存在)
    return nightResId != 0
}

这个方法的核心是通过指定夜间模式的配置,去查找同名同类型的资源,如果能拿到有效的ID,就说明这个Drawable有对应的夜间变体。

方法二:通过临时Context验证(备选)

如果担心getIdentifier的性能(毕竟它是反射式查找),也可以创建一个临时的Context,切换到夜间模式后尝试获取资源,对比原资源是否有差异:

fun hasNightModeDrawable(context: Context, drawableResId: Int): Boolean {
    val originalDrawable = ContextCompat.getDrawable(context, drawableResId) ?: return false
    
    // 创建夜间模式的Context
    val nightContext = context.createConfigurationContext(
        Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES }
    )
    val nightDrawable = ContextCompat.getDrawable(nightContext, drawableResId) ?: return false
    
    // 如果两个Drawable不是同一个实例(说明有不同变体),返回true
    return originalDrawable !== nightDrawable
}

不过这个方法会实际加载Drawable,可能比第一种方法开销大一点,适合不频繁调用的场景。

结合Glide场景使用

拿到判断结果后,就可以优化你的签名逻辑了:

val drawableRes = R.drawable.your_target_drawable
// 判断当前是否处于深色模式
val isInDarkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES

// 只有当存在夜间变体时,才用区分明暗的签名
val signature = if (hasNightModeDrawable(context, drawableRes)) {
    ObjectKey(drawableRes.toString() + if (isInDarkMode) "_dark" else "_light")
} else {
    ObjectKey(drawableRes.toString())
}

// 之后正常用这个签名加载资源即可
Glide.with(context)
    .load(drawableRes)
    .signature(signature)
    .into(imageView)

小提醒

如果你的项目里需要频繁检查资源,建议把检查结果缓存起来(比如用HashMap<Int, Boolean>),避免重复执行查找逻辑,提升性能。

备注:内容来源于stack exchange,提问作者ubuntudroid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 08:49:34