In the Markwon library, I want to add a plugin that will show an image from the application resources if write ![alt text](drawable://icon_name)
in markdown format.
The code below works. But tintColor
is not applied to the image. Because of this, it is not visible in the dark theme. Therefore, I added the value of the android.R.attr.colorControlNormal
resource to change the tintColor
of the drawable. Apparently Markwon erases this value (it is in the markup of the drawable file in the format "?attr/colorControlNormal"
.
It worked. But the color does not change when switching to a dark theme. The value of the android.R.attr.colorControlNormal
attribute remains the same as with the white theme. What could be the mistake?
When this drawable is used directly in markup on the toolbar or other places, the tintColor
is changed according to the theme.
The issue with context
. When an instance of markwon
provided by Hilt with @ApplicationContext
, the tintColor
is incorrect. If create the instance of markwon
locally in a fragment, the tintColor
will be correct.
val tintColor = MaterialColors.getColor(context, android.R.attr.colorControlNormal, Color.RED)
// https://noties.io/Markwon/docs/v4/image/#custom-schemehandler
class DrawableImagesConfigure(private val context: Context) : ImagesPlugin.ImagesConfigure {
override fun configureImages(plugin: ImagesPlugin) {
plugin.addSchemeHandler(schemeHandler)
}
private val schemeHandler = object : SchemeHandler() {
@SuppressLint("DiscouragedApi")
// will handle URLs like `drawable://ic_account_24dp_white`
override fun handle(raw: String, uri: Uri): ImageItem {
val drawableName = raw.substring("drawable://".length)
val drawableId = context.resources.getIdentifier(drawableName, "drawable", context.packageName)
// it's fine if it throws, async-image-loader will catch exception
val drawable: Drawable = AppCompatResources.getDrawable(context, drawableId)
?: throw Exception("The drawable with drawableId $drawableId does not exist")
// every time the same value
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")
}
}
}
<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>
// Fragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DrawableImagesConfigure.updateTintColor(requireContext())
}
class DrawableImagesConfigure(@ApplicationContext private val context: Context) : ImagesPlugin.ImagesConfigure {
private val schemeHandler = object : SchemeHandler() {
override fun handle(raw: String, uri: Uri): ImageItem {
// ...
DrawableCompat.setTint(drawable, tintColorState.value)
// ...
}
// ...
}
companion object {
private val tintColorState = MutableStateFlow(Color.RED)
fun updateTintColor(context: Context) {
tintColorState.value = MaterialColors.getColor(context, android.R.attr.colorControlNormal, Color.RED)
}
}
}