Search code examples
androidhtmlwebviewandroid-jetpack-compose

WebView overlap the entire Compose screen


I'm trying to use WebView on compose screen just to show the html content. But for reasons unknown to me it overlap the entire screen.

Html content:

"<p><strong></strong></p> \n<p><span>Test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test <a href=\"https://domopult.ru/\">link</a></span></p> \n<span><br></span> \n<p><span><strong>List 1:</strong></span></p> \n<p></p> \n<ul> \n <li>element 1 </li> \n <li>element 2 </li> \n <li>element 3 </li> \n</ul> \n<p></p> \n<br> \n<p><strong>List 2:</strong><br></p> \n<ol> \n <li>Element 1 </li> \n <li>Element 2 </li> \n <li>Element 3</li> \n</ol> \n<p></p>"

That is how it should looks like:

enter image description here

That is how it realy looks like:

enter image description here

I tried to use Html.fromHtml(...) and HtmlCompat.fromHtml(...) with the regular Text(text: AnnotatedString) composable. But these classes can't decode <ol> and <p> tags correctly.

Code snippet:

@Composable
fun ServiceDescription(
    service: Service,
    onImageClick: () -> Unit
) {
    val serviceDescription = service.description ?: ""

    Column(modifier = Modifier.fillMaxWidth()) {
        AttachedImages(
            images = service.files,
            onImageClick = { image -> onImageClick() }
        )
        ServiceName(
            modifier = Modifier.padding(horizontal = 16.dp),
            serviceName = service.name ?: ""
        )
        if (service.hasPrice()) {
            ServicePrice(
                modifier = Modifier.padding(horizontal = 16.dp),
                price = service.price,
                productName = service.productName ?: "",
                priceDescription = service.priceDescription ?: ""
            )
        }
        Spacer(modifier = Modifier.height(24.dp))

        if (service.hasDescription()) {
            Column(
                modifier = Modifier.fillMaxWidth(),
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                Text(
                    modifier = Modifier.padding(horizontal = 16.dp),
                    text = stringResource(id = R.string.request_description),
                    color = ColorDomopult.BasicOnBgPrimary,
                    style = DomopultTypography.body1,
                    fontWeight = FontWeight.W600
                )

                AndroidView(
                    modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
                    factory = { context ->
                        WebView(context).apply {
                            layoutParams = ViewGroup.LayoutParams(
                                ViewGroup.LayoutParams.MATCH_PARENT,
                                ViewGroup.LayoutParams.WRAP_CONTENT
                            )
                            settings.javaScriptEnabled = true
                            loadDataWithBaseURL(
                                null,
                                serviceDescription,
                                "html",
                                "utf-8",
                                null,
                            )
                        }
                    }
                )
            }
        }
    }
}

Of course if I use loadUrl("https://www.google.com") instead of loadDataWithBaseURL(....) , the UI state would be as expected.

enter image description here

How do I show html content inside WebView?


Solution

  • Thanks to Yap from ComposeMpp community.

    Need to use .clipToBounds() modifier.

    AndroidView(
      modifier = Modifier
          .fillMaxWidth()
          .padding(horizontal = 16.dp)
          .clipToBounds(),
      factory = { context ->
        WebView(context).apply {
          layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
          )               
          setBackgroundColor(ColorDomopult.BasicBgPrimary.toArgb())
          settings.javaScriptEnabled = true
          loadDataWithBaseURL(
            null,
            service.description ?: "",
            "text/html",
            "utf-8",
            null
          )
        }
      }
    )