1

I'm building a Jetpack Compose screen that has an AppBar at the top and a WebView below it using AndroidView.

  • The problem is that the AppBar takes a noticeable moment to appear when the screen loads.
  • It seems like the presence of AndroidView (with the WebView) causes this delay.
  • When the AndroidView is removed AppBar loads instantly.
@Composable
fun LicenseScreen(
    backgroundColor: Int,
    handleMenuEvent: (MenuEvent) -> Unit,
) {
    val context = LocalContext.current
    Column(
        verticalArrangement = Arrangement.Top,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier
            .fillMaxSize()
            .background(
                color = colorResource(id = backgroundColor),
                shape = RoundedCornerShape(
                    topStart = 15.dp,
                    topEnd = 15.dp,
                    0.dp,
                    0.dp,
                ),
            ),
    ) {
        AppBar( "Notice License", backgroundColor) { handleMenuEvent(TopMenuItemEvent.OnBackClicked) }

        val licenceUrl =  "file:///android_asset/notice_license.html"

        AndroidView(
            modifier = Modifier.wrapContentSize(),
            factory = {
                WebView(context).apply {
                    loadUrl(licenceUrl)
                }
            },
        )
    }
}

❓ My Questions:

  • Why does the AppBar render with a delay when AndroidView is present?
  • Is there a way to ensure the AppBar renders immediately, regardless of the WebView loading?
2
  • In my quick tests, it's even worse, and the app bar doesn't appear at all until you scroll the WebView. I'm not sure why, but wrapping the WebView in a FrameLayout seems to fix it. I got the suggestion from stackoverflow.com/a/79465237, but I'm not yet sure if it's just a fluke in my setup. I'll investigate further when I get a chance later. Commented Apr 1 at 19:38
  • OK, I think I know what the problem is, in broad strokes, anyway. The WebView's rendering is kinda "bleeding" outside of its bounds, but it only draws content inside, so when it invalidates itself after everything else is done, it ends up erasing everything outside. I just happened to have come across this recently working a different issue, and the solution is to add graphicsLayer { clip = true } to the AndroidView's Modifier. That will contain its rendering to its own bounds, preventing it from clearing everything else, and your app bar should show immediately. Commented Apr 2 at 2:41

1 Answer 1

1

The performance of AndroidView is not great and it delays the whole composition. The easiest workaround I found is to wrap your AndroidView into a LazyColumn like this:

LazyColumn {
    item {
        AndroidView(
            modifier = Modifier.wrapContentSize(),
            factory = {
                WebView(context).apply {
                    loadUrl(licenceUrl)
                }
            },
        )
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Issue still present with latest Compose libraries, the only solution to make it working is this LazyColumn workaround.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.