I have composable hierarchy such as Box -> Android...
# compose
o
I have composable hierarchy such as Box -> AndroidView -> SurfaceView. • Initially the layout is layout out as expected where i see the surfaceview filling up the box • When the size of the Box changes from one size (Larger) to another (Smaller) the ui is expected, Surfaceview fills up the box • Change the orientation • Now change the size of the Box from Smaller to lager, this leads to a bug where the Surfaceview is not filling up the parent as is the same Smaller size. • If i change the orientation again, the surfaceview now fills up the box and everything seems normal as before Is this known bug with the surfaceview inside the AndroidView?
r
Does this happens only with the Surface view? Might be worth reporting the bug if so If not Android view factory provides you with update method where you can adjust the layout parameters view after recomposition and there you could probably solve your issue
o
I only tried with with surfaceview so unsure about the rest I did try to set the layout params to the size of the android view but still no luck there inside the udpate getting it form the onSizeChanged modifier
r
you can also try to remember container size state and change the surfaceview params after onSizeChanged
o
did that, still no luck
Copy code
@Composable
private fun BoxScope.PlayerVideo(
    modifier: Modifier = Modifier,
    orientationValue: OrientationValue,
    resizeValue: ResizeValue,
    videoAspectRatioValue: Float,
    onSurfaceViewAttachedToWindow: (SurfaceView) -> Unit,
    onSurfaceViewDetachedFromWindow: (SurfaceView) -> Unit,
) {
    var size by remember { mutableStateOf(IntSize.Zero) }
    AndroidView(
        modifier = modifier
            .align(Alignment.Center)
            .fillMaxSize()
            .onSizeChanged {
                Logger.d("TEST", "Size Changed")
                size = it
            }
            .border(2.dp, Color.Red),
        factory = { context ->
            Logger.d("TEST", "Create View")
            AspectRatioLayout(context).apply {
                layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
                setAspectRatio(videoAspectRatioValue)
                setResizeMode(RESIZE_MODE_FIT)
                addView(SurfaceView(context).apply {
                    layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
                    addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
                        override fun onViewAttachedToWindow(view: View) =
                            onSurfaceViewAttachedToWindow(view as SurfaceView)

                        override fun onViewDetachedFromWindow(view: View) =
                            onSurfaceViewDetachedFromWindow(view as SurfaceView)
                    })
                })
            }
        },
        update = { view ->
            Logger.d("TEST", "Update View")
            val aspectRatioLayout = view as AspectRatioLayout
            aspectRatioLayout.setAspectRatio(videoAspectRatioValue)

            // TODO: change orientation to window size class
            when (orientationValue) {
                OrientationValue.LANDSCAPE -> when (resizeValue) {
                    ResizeValue.FIT -> aspectRatioLayout.setResizeMode(RESIZE_MODE_FIT)
                    ResizeValue.ZOOM -> aspectRatioLayout.setResizeMode(RESIZE_MODE_ZOOM)
                }

                OrientationValue.PORTRAIT -> aspectRatioLayout.setResizeMode(RESIZE_MODE_FIXED_WIDTH)
            }

            aspectRatioLayout.layoutParams = FrameLayout.LayoutParams(size.width, size.height)
            aspectRatioLayout.invalidate()
            aspectRatioLayout.requestLayout()
            aspectRatioLayout.getChildAt(0).layoutParams = FrameLayout.LayoutParams(size.width, size.height)
            aspectRatioLayout.getChildAt(0).invalidate()
            aspectRatioLayout.getChildAt(0).requestLayout()
        }
    )
}
r
maybe the aspect ratio is ruining something? with this quick snippet everything scales out perfectly when changing orientation
Copy code
fun Composable() {
    val context = LocalContext.current
    val config = LocalConfiguration.current
    val isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT

    Box(modifier = Modifier.size(if(isPortrait) 100.dp else 200.dp)) {
        AndroidView(factory = {
            val view = SurfaceView(context)
            view.setBackgroundColor(ContextCompat.getColor(context, R.color.teal_200))
            view.layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
            view
        })
    }
}
o
Copy code
val surfaceView = view.findViewById<SurfaceView>(R.id.surface_view)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
    surfaceView.getRootSurfaceControl()?.let { rootSurfaceControl ->
        val surfaceSyncGroup = SurfaceSyncGroup("exo-sync-b-334901521")
        surfaceSyncGroup.add(rootSurfaceControl) { }
        surfaceSyncGroup.markSyncReady()
        surfaceView.invalidate()
        rootSurfaceControl.applyTransactionOnDraw(SurfaceControl.Transaction())
    }
}
the above helped me solve the problem