Hi, I'm having a bit of a problem with the new Con...
# compose
o
Hi, I'm having a bit of a problem with the new ContentFrame that wraps PlayerSurface to give video playback in native compose. I'm using it in this composable:
Copy code
@androidx.annotation.OptIn(UnstableApi::class)
@Composable
fun VideoPlayer(
 modifier: Modifier,
 uri: Uri,
 startTimeMs: Long,
 endTimeMs: Long
) {
   val context = LocalContext.current
  val mediaItem = MediaItem.fromUri(uri)
  val exoPlayer = remember {
      ExoPlayer.Builder(context).build()
    }
LaunchedEffect(uri, startTimeMs, endTimeMs) {
      exoPlayer.setMediaItem(MediaItem.fromUri(uri))
     exoPlayer.seekTo(startTimeMs)
      exoPlayer.playWhenReady = true
   }
  LaunchedEffect(exoPlayer, startTimeMs, endTimeMs) {
    //Some stuff    
   }
  DisposableEffect(Unit) {
     onDispose {
         exoPlayer.release()
        }
    }
  Box {
       ContentFrame(
         player = exoPlayer
       )
    }
}
``` And then I have a composable DraggableContainer which I use to move texts or stickers over the image or video playing. It works fine when it's used over an image (coil AsyncImage). But when it's placed over VideoPlayer in a Box, I lose the ability to drag the texts or the stickers around. Note: DraggableContainer uses graphicsLayer in its implementation. Similar things occur where I couldn't drag the RangeSlider from Material3 when VideoPlayer (which uses ContentFrame or PlayerSurface) was beneath it in a Box. I also tried setting useTextureView (or something like that), but got the same result. Maybe I need to set texture view but also simultaneously increase the z-axis of my DraggableContainer? I don't really know though, kinda a beginner. Here's some more code for context: Codes in thread
🧵 4
Ok sir. Thanks.
Copy code
Box {
    if (isVideo) {
       VideoPlayer(
           modifier = videoSizeGetModifier,
           uri = uri,
ong(),
         endTimeMs = (endTime * 1000).toLong()
        )
    } else {
        AsyncImage(
            model = ImageRequest.Builder(context)
                .data(mediaUri)
                .crossfade(true)
                .build(),
            contentDescription = "Selected image",
            modifier = Modifier
                .fillMaxSize()
                .onSizeChanged {
                    viewModel.updateContainerSize(it)
                },
            onSuccess = { state ->
                mediaIntrinsicSize = state.painter.intrinsicSize
            }
        )
    }
    
    DraggableContainer(
        children = uiState.overlayTexts,
        stickers = uiState.overlayStickers,
        overlayInteraction = uiState.overlayInteraction,
        onChildTransformChanged = { id, offset, rotation, scale ->
            val contentRect = calculateContentRect(containerSize, mediaIntrinsicSize)
            if (contentRect != Rect.Zero) {
                val relativeRatioX = (offset.x - contentRect.left) / contentRect.width
                val relativeRatioY = (offset.y - <http://contentRect.top|contentRect.top>) / contentRect.height

                viewModel.transformOverlayText(
                    id = id,
                    offset = offset,
                    positionX = relativeRatioX,
                    positionY = relativeRatioY,
                    rotation = rotation,
                    scale = scale
                )
            }
        },
        onStickerTransformChanged = { id, offset, rotation, scale, parentSize, currentStickerSize ->
            //Some stuff,
        onChildClick = {
            viewModel.selectOverlay(it)
            editing.value = true
        },
        modifier = Modifier.matchParentSize()
    )
}
Copy code
@Composable
fun DraggableContainer(
    children: List<TextOverlay>,
    stickers: List<OverlaySticker>,
    onChildTransformChanged: (id: String, offset: Offset, rotation: Float, scale: Float) -> Unit,
    onStickerTransformChanged: (id: String, offset: Offset, rotation: Float, scale: Float, parentSize: Size, currentStickerSize: Size) -> Unit,
    overlayInteraction: OverlayInteraction,
    onChildClick: (String) -> Unit,
    modifier: Modifier = Modifier
) {
    val density = LocalDensity.current
    val childSizes = remember { mutableStateMapOf<String, Size>() }
    val stickerSizes = remember { mutableStateMapOf<String, Size>() }

    val currentChildren by rememberUpdatedState(children)
    val currentStickers by rememberUpdatedState(stickers)

    BoxWithConstraints(modifier) {
        val parentWidth = constraints.maxWidth.toFloat()
        val parentHeight = constraints.maxHeight.toFloat()

        when (overlayInteraction) {
            is OverlayInteraction.Selected -> {}
            else -> {
                children.forEach { child ->
                    if (child.text.isNotEmpty()) {
                        Box(
                            modifier = Modifier
                                .graphicsLayer {
                                    translationX = child.offsetRatioX * parentWidth
                                    translationY = child.offsetRatioY * parentHeight
                                    rotationZ = child.rotation
                                    scaleX = child.scale
                                    scaleY = child.scale
                                }
                                .onSizeChanged {
                                    childSizes[child.id] = Size(it.width.toFloat(), it.height.toFloat())
                                }
                        ) {
                            OverlayText(
                                text = child.text,
                                onClick = { },
                                maxWidth = with(density) { (parentWidth / child.scale).toDp() },
                                maxHeight = with(density) { (parentHeight / child.scale).toDp() },
                                textStyle = child.config.textStyle,
                                containerColor = child.config.containerColor
                            )
                        }
                    }
                }
                // stickers logic...
            }
        }

        // GESTURE OVERLAY
        Box(
            modifier = Modifier
                .fillMaxSize()
                .zIndex(1f)
                .pointerInput(Unit) {
                    detectTapGestures(
                        onTap = { tapOffset ->
                            val clickedChild = currentChildren.asReversed().find { child ->
                                val size = childSizes[child.id] ?: Size.Zero
                                val centerX = child.offsetRatioX * parentWidth + (size.width * child.scale / 2)
                                val centerY = child.offsetRatioY * parentHeight + (size.height * child.scale / 2)
                                isPointInRotatedBox(
                                    tapOffset,
                                    Offset(centerX, centerY),
                                    Size(size.width * child.scale, size.height * child.scale),
                                    child.rotation
                                )
                            }
                            if (clickedChild != null) onChildClick(clickedChild.id)
                        }
                    )
                }
        )
    }
}