kotlinandroid-jetpack-composeandroid-webviewfont-size

Webview doesn't recompose upon change of mutableIntState


enter image description here

The design of my article details page is as follows: the upper section is native, while the rest of the article (images, embeds, tweets...) is received as an HTML content.

I want to implement font resize feature, and for that I've used mutableIntState, which causes the title and summary to be recomposed whenever the Slider has a new value.

Unfortunately it doesn't affect the webview! Although I've created a custom webview composable that takes the following parameters:

  1. fontSize
  2. html: string value representing an HTML snippet, which later I wrap it with CSS to give it the font size.

ViewModel:

class PageViewModel: ViewModel(){
    //get initial value from sharedPreferences
    var fontSize by mutableIntStateOf(Utility.getFontSize())
        private set

    fun updateFontSize(newValue:Int){
        fontSize = newValue
        //store new value in shared preferences
        Utility.saveFontSize(newValue)
    }
}

MyScreen:

    @Composable
    fun MyScreen(title: String, summary: String, html: String){
        val myViewModel: PageViewModel = viewModel()
    Column{
    ....
        //the slider enables the user to select a value ranging between 16f & 26f
        Slider(onValueChange = {myViewModel.updateFontSize(it.toInt())},
             steps = 3, valueRange= 16f .. 26f, value = myViewModel.fontSize.toFloat())
        
    ...
        Text(text = title, fontSize = (myViewModel.fontSize + 6).dp)
        Text(text = summary, fontSize = myViewModel.fontSize.dp)
        MyCustomWebView(html = html, fontSize = fontSize) 
    }
 }

My Custom Webview is as follows:

@Composable
fun MyCustomWebView(html:String, fontSize: Int){
    val context = LocalContext.current
    //assuming that html is an html snippet
    val htmlStyled = "<html><head><style>body,p,h1,h2,h3,span,a{font-size: ${fontSize}px!important;}</style></head><body>${html}</body></html>"
    AndroidView(modifier = Modifier.fillMaxWidth(),
         factory = {
                WebView(context).apply{
                      webViewClient = WebViewClient()
                      settings.cacheMode = WebSettings.LOAD_NO_CACHE
                      settings.setRenderPriority(WebSettings.RenderPriority.HIGH)
                      settings.javaScriptEnabled = true
                      settings.domStorageEnabled = true
                      settings.allowFileAccess = true
                      
                      //I even tried using the deprecated textSize
                      //It doesn't update live
                      /*settings.textSize = when (fontSize) {
                        16 -> WebSettings.TextSize.SMALLEST
                        18 -> WebSettings.TextSize.SMALLER
                        21 -> WebSettings.TextSize.NORMAL
                        23 -> WebSettings.TextSize.LARGER
                        else -> WebSettings.TextSize.LARGEST
                    }*/
                     
                     loadDataWithBaseURL("", htmlStyled, "text/html", "UTF-8","")
                }
         }
}

Any help is most appreciated.

Thanks.


Solution

  • In the AndroidView one must use update value-parameter.. so the customWebView becomes as follows:

    @Composable
    fun MyCustomWebView(html:String, fontSize: Int){
    .......
        AndroidView(modifier = Modifier.fillMaxWidth(),
             factory = {...},
             update = { it.settings.textZoom =   fontSize * 6
             })
      }