-
-
Save skydoves/ac7cf43b970c0df13e918130b2d2f11e to your computer and use it in GitHub Desktop.
floating_video_renderer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2023 Stream.IO, Inc. All Rights Reserved. | |
// SPDX-License-Identifier: Apache-2.0 | |
@Composable | |
fun FloatingVideoRenderer( | |
videoTrack: VideoTrack, | |
parentBounds: IntSize, | |
paddingValues: PaddingValues, | |
modifier: Modifier = Modifier | |
) { | |
var videoSize by remember { mutableStateOf(IntSize(0, 0)) } | |
var offsetX by remember { mutableStateOf(0f) } | |
var offsetY by remember { mutableStateOf(0f) } | |
val offset by animateOffsetAsState(targetValue = Offset(offsetX, offsetY)) | |
val density = LocalDensity.current | |
LaunchedEffect(parentBounds.width) { | |
offsetX = 0f | |
offsetY = 0f | |
} | |
val paddingOffset = density.run { 16.dp.toPx() } | |
Card( | |
elevation = 8.dp, | |
modifier = Modifier | |
.offset { IntOffset(offset.x.toInt(), offset.y.toInt()) } | |
.pointerInput(parentBounds) { | |
detectDragGestures { change, dragAmount -> | |
change.consume() | |
val newOffsetX = (offsetX + dragAmount.x) | |
.coerceAtLeast( | |
-calculateHorizontalOffsetBounds( | |
parentBounds = parentBounds, | |
paddingValues = paddingValues, | |
floatingVideoSize = videoSize, | |
density = density, | |
offset = paddingOffset * 2 | |
) | |
) | |
.coerceAtMost( | |
0f | |
) | |
val newOffsetY = (offsetY + dragAmount.y) | |
.coerceAtLeast(0f) | |
.coerceAtMost( | |
calculateVerticalOffsetBounds( | |
parentBounds = parentBounds, | |
paddingValues = paddingValues, | |
floatingVideoSize = videoSize, | |
density = density, | |
offset = paddingOffset * 2 | |
) | |
) | |
offsetX = newOffsetX | |
offsetY = newOffsetY | |
} | |
} | |
.then(modifier) | |
.padding(16.dp) | |
.onGloballyPositioned { videoSize = it.size }, | |
shape = RoundedCornerShape(16.dp) | |
) { | |
VideoRenderer( | |
modifier = Modifier | |
.fillMaxSize() | |
.clip(RoundedCornerShape(16.dp)), | |
videoTrack = videoTrack | |
) | |
} | |
} | |
private fun calculateHorizontalOffsetBounds( | |
parentBounds: IntSize, | |
paddingValues: PaddingValues, | |
floatingVideoSize: IntSize, | |
density: Density, | |
offset: Float | |
): Float { | |
val rightPadding = | |
density.run { paddingValues.calculateRightPadding(LayoutDirection.Ltr).toPx() } | |
return parentBounds.width - rightPadding - floatingVideoSize.width - offset | |
} | |
private fun calculateVerticalOffsetBounds( | |
parentBounds: IntSize, | |
paddingValues: PaddingValues, | |
floatingVideoSize: IntSize, | |
density: Density, | |
offset: Float | |
): Float { | |
val bottomPadding = | |
density.run { paddingValues.calculateBottomPadding().toPx() } | |
return parentBounds.height - bottomPadding - floatingVideoSize.height - offset | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment