Jetpack Compose : How to overlay Composable with AndroidView?

Issue

I’m new to Jetpack Compose and trying to figure out how to solve next task:

I need to create a simple transparent AndroidView. And it needs to be used as an overlay for Composable functions.

The problem is that an overlay should be the same size as a compose view under it.

I had some-kind of successful attempt with this:

@Composable
fun BugseeOverlayView() {
    AndroidView(
        modifier = Modifier.fillMaxSize(),
        factory = { ctx ->
            View(ctx).apply {
                layoutParams = LinearLayout.LayoutParams(200, 200) //Hardcoded size
                alpha = 0.0F
            }
        }, update = {
            Bugsee.addSecureView(it) // 3rd party I need to use
        }
    )
}

And then I used it like:

Box {    
    Box(Modifier.fillMaxSize()) {
        BugseeOverlayView()
    }
    Text("Hide me") // or some 'CustomComposableView(param)'
}

This works, but the size is hardcoded.

PS. I need an AndroidView because of third-party tool which accepts android.view.View as a parameter.

Solution

You can get size of a Composable in various ways.

1- Modifier.onSizeChanged{intSize->} will return Composable size in pixels you can convert this to dp using LocalDensity.current.run{}. With this approach the size you set will change and there needs to be another recomposition. You can also get size of a Composable from Modifier.onGloballyPositioned either.

val density = LocalDensity.current
var dpSize: DpSize by remember{ mutableStateOf(DpSize.Zero) }
Modifier.onSizeChanged { size: IntSize ->
    density.run { dpSize = DpSize(size.width.toDp(), size.height.toDp()) }
}
Modifier.onGloballyPositioned {layoutCoordinates: LayoutCoordinates ->
    val size = layoutCoordinates.size
    density.run { dpSize = DpSize(size.width.toDp(), size.height.toDp()) }
}

2- If the Composable has fixed size or covers screen you can use

BoxWithConstraints {
   SomeComposable()
   AndroidView(modifier=Modifier.size(maxWidth, maxHeight)
}

3- If you don’t have chance to get Composable size and don’t want to have another recomposition you can use SubcomposeLayout. Detailed answer is available here how to create a SubcomposeLayout to get exact size of a Composable without recomposition.

When you are able to get size of Composable you can set same size to AndroidView and set layout params to match parent. If that’s not what you wish you can still set Modifier.fillMaxSize while using methods above to set layout params

Answered By – Thracian

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published