I'm trying to change a WebView color for dark mode. For some reason, the steps described in Darken web content in WebView do not produce the wanted result. So I was thinking of inverting the colors of each pixel. Would that be possible during composition?
The following is the code I have:
val activity = LocalActivity.current!!
AndroidView(modifier = Modifier
.background(colorResource(R.color.white), RoundedCornerShape(10))
.padding(16.dp),
factory = {
WebView(it)
// The code that seems to have no effect is from here...
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
settings.setAlgorithmicDarkeningAllowed(true)
} else if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
when (activity.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> {
WebSettingsCompat.setForceDark(settings, FORCE_DARK_ON)
}
Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> {
WebSettingsCompat.setForceDark(settings, FORCE_DARK_OFF)
}
else -> {
//
}
}
}
}
// ...until here.
}, update = {
val reader = activity.resources.openRawResource(R.raw.about).reader()
val unencodedHtml = reader.readText()
reader.close()
val encodedHtml: String =
Base64.encodeToString(unencodedHtml.toByteArray(), Base64.NO_PADDING)
it.loadData(encodedHtml, "text/html", "base64")
})
So would there be any way of changing the Composable's (ie. AndroidView's) pixels during drawing? Like applying a ColorFilter to an ImageBitmap?
You can use obtainGraphicsLayer
inside onDrawWithCache
or rememberGraphicsLayer()
to get GraphicsLayer
then apply color filter or blendMode directly to content or drawing of Composable.
modifier = Modifier
.drawWithCache {
val graphicsLayer = obtainGraphicsLayer()
val values = floatArrayOf(
-1f, 0f, 0f, 0f, 255f,
0f, -1f, 0f, 0f, 255f,
0f, 0f, -1f, 0f, 255f,
0f, 0f, 0f, 1f, 0f
)
graphicsLayer.apply {
record {
drawContent()
}
// blendMode = BlendMode.Difference
colorFilter = ColorFilter.colorMatrix(ColorMatrix(values))
}
onDrawWithContent {
drawLayer(graphicsLayer)
}
}
Note: BlendMode.Difference or BlendMode.Exclusion requires api 29 and above but you can apply color filter for any api levels.