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

Markwon插件Drawable tint主题切换失效:ApplicationContext问题排查

问题描述

我在Markwon库中开发插件,实现通过Markdown语法![alt text](drawable://icon_name)加载应用内资源图片。目前图片能正常加载,但tintColor不生效,深色主题下图片几乎看不见。我尝试用android.R.attr.colorControlNormal设置Drawable的tintColor,首次启动时正常,但切换主题后颜色不更新;而同样的Drawable直接用在布局(比如工具栏)里时,tint能随主题正常切换。

更新1

问题根源出在context:用Hilt提供的@ApplicationContext创建Markwon实例时,tintColor异常;但在Fragment里本地创建Markwon实例,tintColor就能正常随主题切换。

val tintColor = MaterialColors.getColor(context, android.R.attr.colorControlNormal, Color.RED)

深色主题下图标不可见
正常显示的图标

现有代码

DrawableSchemeHandler实现

// 参考Markwon图片自定义SchemeHandler文档
class DrawableImagesConfigure(private val context: Context) : ImagesPlugin.ImagesConfigure {

    override fun configureImages(plugin: ImagesPlugin) {
        plugin.addSchemeHandler(schemeHandler)
    }

    private val schemeHandler = object : SchemeHandler() {
        @SuppressLint("DiscouragedApi")
        // 处理`drawable://ic_account_24dp_white`这类URL
        override fun handle(raw: String, uri: Uri): ImageItem {
            val drawableName = raw.substring("drawable://".length)
            val drawableId = context.resources.getIdentifier(drawableName, "drawable", context.packageName)

            // 允许抛出异常,async-image-loader会捕获
            val drawable: Drawable = AppCompatResources.getDrawable(context, drawableId)
                ?: throw Exception("ID为$drawableId的Drawable不存在")

            // 每次获取的颜色值都一样,不随主题变化
            val tintColor = MaterialColors.getColor(context, android.R.attr.colorControlNormal, Color.RED)
            drawable.setTint(tintColor)
            return ImageItem.withResult(drawable)
        }

        override fun supportedSchemes(): Collection<String> {
            return setOf("drawable")
        }
    }
}

矢量Drawable资源

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:tint="?attr/colorControlNormal"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="@android:color/white"
        android:pathData="M4,15h16c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1L4,13c-0.55,0 -1,0.45 -1,1s0.45,1 1,1zM4,19h16c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1L4,17c-0.55,0 -1,0.45 -1,1s0.45,1 1,1zM4,11h16c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1L4,9c-0.55,0 -1,0.45 -1,1s0.45,1 1,1zM3,6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1L4,5c-0.55,0 -1,0.45 -1,1z" />
</vector>
解决方案
  1. 使用与主题绑定的Context
    ApplicationContext是全局上下文,不随Activity/Fragment的主题变化而更新,所以获取的属性值始终是应用启动时的主题颜色。需要改用Activity或Fragment的Context来创建Markwon实例和处理Drawable加载。
    如果用Hilt注入,不要直接注入@ApplicationContext,而是在Activity/Fragment中注入@ActivityContext或直接使用requireContext()(Fragment中)。

  2. 使用TintList而非固定颜色值
    不要用setTint()设置单一颜色,而是用setTintList()绑定属性值,让Drawable自动跟随主题变化:

// 替换原有的setTint代码
val tintList = ContextCompat.getColorStateList(context, android.R.attr.colorControlNormal)
drawable.setTintList(tintList)

这样Drawable会根据当前上下文的主题自动更新tint颜色,即使主题切换也能同步变化。

  1. 避免提前缓存Drawable
    Markwon的SchemeHandler如果缓存了Drawable实例,主题切换时不会重新加载,所以要确保每次处理请求时都重新获取Drawable并设置tintList,或者监听主题变化事件触发Markwon重新渲染内容。

内容的提问来源于stack exchange,提问作者Viewed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:43:21