Unable to Achieve Full-Screen View Transition in Jetpack Compose android

66 Views Asked by At

I'm working on a Compose app where I need a custom view to expand to full screen when dragged up and return to its original size when dragged down. However, my current implementation isn't achieving the desired result.

Problem: Unable to smoothly transition the view to full screen upon dragging.

Approach: Using Modifier.offset and pointerInput to detect drag gestures.

Request: Seeking guidance on achieving a smooth transition for the view to go full screen and back.

Current Behavior: The custom view, located within a bottom app bar and sized around 200dp, does not transition to full screen as intended when dragged up. Expected Behavior: When the user drags the custom view upward, it should smoothly transition to a full-screen view. Conversely, when dragged downward, it should revert to its original size within the bottom app bar.

Any insights or suggestions would be greatly appreciated!

Here's a breakdown of the problem

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PostMediaContent(
mediaPaths: List<Pair<Int, String>>,
navController: NavController,
pagerState: PagerState,
viewModel: FilterScreenViewModel,
onTabChange: (index: Int) -> Unit = {},
onMediaSelected: (List<Pair<Int, String>>) -> Unit
) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
var inSelectionMode by remember { mutableStateOf(false) }
var isVideo by remember { mutableStateOf(false) }
var selectedImageId by remember { mutableStateOf(mediaPaths.firstOrNull()?.first ?: -1) }
val selectedImageIds = remember { mutableStateOf(setOf<Int>()) }
var selectedImagePath by remember { mutableStateOf(mediaPaths.firstOrNull()?.second ?: "") }
val isFullScreen = remember { mutableStateOf(false) }
val topPadding = remember { mutableStateOf(0.dp) }
LaunchedEffect(mediaPaths) {
    if (mediaPaths.isNotEmpty()) {
        selectedImagePath = mediaPaths.first().second
        isVideo = selectedImagePath?.endsWith(".mp4", ignoreCase = true) ?: false
    }
}

val offsetY = remember { mutableStateOf(0f) }
Box(
    modifier = Modifier
        .fillMaxSize()
        .padding(top = 56.dp)
) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .align(Alignment.TopCenter)
    ) {
                Column(
                    verticalArrangement = Arrangement.spacedBy((-60).dp)
                ) {
                    if (isVideo) {
                        val zoomState = rememberZoomState()
                        Box(
                            modifier = Modifier
                                .background(Color.Black)
                                .height(400.dp)
                                .fillMaxWidth()
                                .snapBackZoomable(
                                    zoomState = zoomState,
                                )
                                .clickable {
                                }
                        ) {
                            VideoPlayer(
                                videoUrl = selectedImagePath
                            )
                            onMediaSelected(
                                listOf(selectedImageId to selectedImagePath)
                            )
                        }
                    } else {
                        val zoomState = rememberZoomState()
                        AsyncImage(
                            model = ImageRequest
                                .Builder(LocalContext.current)
                                .data(selectedImagePath)
                                .build(),
                            onSuccess = { state ->
                                zoomState.setContentSize(state.painter.intrinsicSize)
                            },
                            modifier = Modifier
                                .height(400.dp)
                                .fillMaxWidth()
                                .snapBackZoomable(
                                    zoomState = zoomState,
                                ),
                            contentDescription = null,
                            contentScale = ContentScale.Crop
                        )
                        onMediaSelected(
                            listOf(selectedImageId to selectedImagePath)
                        )
                    }
                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(horizontal = 20.dp)
                            .background(Color.Transparent)
                    ) {
                        Image(
                            painter = painterResource(id = R.drawable.core_ui_ic_tab_expand),
                            contentDescription = stringResource(id = R.string.regular_post_expand_toast),
                            modifier = Modifier.clickable {
                            }
                        )
                        Row(
                            horizontalArrangement = Arrangement.End,
                            modifier = Modifier.fillMaxWidth()
                        ) {
                            Image(
                                painter = painterResource(id = R.drawable.core_ui_ic_tab_multiselect),
                                contentDescription = stringResource(id = R.string.regular_post_multi_toast),
                                modifier = Modifier.clickable {
                                    inSelectionMode = true
                                }
                            )
                        }

                    }
                }

// here is the main code where is the gesture is implemneted
        Box(
            modifier = Modifier
                .offset { IntOffset(0, offsetY.value.toInt()) }
                .pointerInput(Unit) {
                    detectVerticalDragGestures(
                        onDragStart = { offsetY.value = 0f },
                        onDragEnd = {
                            isFullScreen.value = offsetY.value < 1000.dp.toPx()
                            offsetY.value = 0f
                            topPadding.value = if (isFullScreen.value) 56.dp else 0.dp
                        }
                    ) { change, dragAmount ->
                        offsetY.value += dragAmount
                        change.consumeAllChanges() // Consume the drag event
                    }
                }
        ) {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .then(if (isFullScreen.value) Modifier.fillMaxHeight() else 
 Modifier.height(1000.dp).fillMaxWidth())
                    .padding(top = topPadding.value)
            ) {
                GalleryTabsComposable(
                    pagerState = pagerState,
                    onTabChange = { index ->
                        coroutineScope.launch {
                            pagerState.animateScrollToPage(index)
                        }
                    })
                HorizontalPager(
                    state = pagerState,
                    modifier = Modifier.background(Color.Black)
                ) { page ->
                    when (PostTabs.entries[page]) {
                        PostTabs.GALLERY -> {
                            PostPhotoGrid(
                                navController = navController,
                                mediaPaths(context),
                                inSelectionMode,
                                viewModel,
                                onImageClick = { imagePath ->
                                    selectedImagePath = imagePath
                                    if (imagePath.endsWith(".mp4", true) ||
                                        imagePath.endsWith("webm", true)
                                    ) {
                                        isVideo = true
                                    }
                                    selectedImageId =
                                        mediaPaths.find { it.second == imagePath }?.first ?: -1
                                    if (inSelectionMode) {
                                        if (selectedImageIds.value.contains(selectedImageId)) {
                                            selectedImageIds.value - selectedImageId
                                        } else {
                                            selectedImageIds.value + selectedImageId
                                        }
                                    }
                                }
                            )
                        }
                        else -> {
                            DraftPhotoGrid(
                                navController = navController,
                            )
                        }
                    }
                }
            }
        }
    }
}
}
@Preview
  @Composable
fun PostMediaContentPreview() {
val pagerState = rememberPagerState(pageCount = { 3 })
val navController = rememberNavController()

val dummyMediaPaths = listOf(
    1 to "https://picsum.photos/id/237/200/300",
    2 to "https://picsum.photos/id/238/200/300",
    3 to "https://picsum.photos/id/239/200/300"
)

PostMediaContent(
    mediaPaths = dummyMediaPaths,
    navController = navController,
    pagerState = pagerState,
    viewModel = hiltViewModel(),
    onTabChange = {},
    onMediaSelected = {}
)
}

Thank you in advance for your assistance!

0

There are 0 best solutions below