Jetpack compose - animateDp - animation not showing in false case

195 Views Asked by At

I am trying to build a dialog bottom sheet, which i need to show a bottom sheet like thing over all composables with that sliding up and down, also with touch outside to dismiss behaviour. In order to show above all elements i wrapped this in to a dialog and used update transition to translate height of the card inside dialog which is made to appear at the bottom of the screen. The visibility is handled by a boolean value . The issue is that the animation is showing when when visibility is true. But it just fades out when visibility is false instead of showing sliding down animation.

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun DialogBottomSheets(
    isVisible: Boolean,
    onDismiss: () -> Unit,
    content: @Composable () -> Unit,
    modifier: Modifier = Modifier
) {
    val mutableInteractionSource = MutableInteractionSource()

    var visibility by remember(isVisible) {
        mutableStateOf(isVisible)
    }

    val transition = updateTransition(visibility, label = "Translation")
    val screenHeight = rememberWindowInfo().screenHeight

    val translateY by transition.animateDp(
        transitionSpec = {
            tween(200)
        }, label = "TranslationY to card"
    ) { isVisible ->
        if (isVisible) 0.dp else screenHeight
    }

    AnimatedVisibility(
        visible = visibility,
        enter = fadeIn(
            animationSpec = keyframes {
                this.durationMillis = 200
            }
        ),
        exit = fadeOut(
            animationSpec = keyframes {
                this.durationMillis = 200
            }
        ),
        modifier = modifier
            .fillMaxSize()
            .zIndex(2f)
    ) {

        Dialog(
            onDismissRequest = { onDismiss() },
            properties = DialogProperties(
                usePlatformDefaultWidth = false,
                ),
        ) {
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(color = Color.Transparent)
                    .clickable(mutableInteractionSource, null) {
                        Log.i("ONCLICK-DialogBottomSheets","Box")
                        onDismiss()
                    }
                ,
                contentAlignment = Alignment.BottomCenter
            ) {
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .wrapContentHeight()
                        .offset(x = 0.dp, y = translateY)
                        .zIndex(2f)
                      /*  .clickable(mutableInteractionSource, null) {
                            // Nothing here to override click above the cards to implement dismiss on click outside behaviour
                        }*/
                    ,
                    backgroundColor = Color.White,
                    shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp)
                ) {
                    content()
                }
            }
        }


    }


}

Compose version - 1.2.0. I cant use Bottom sheet from compose as this is built for project which interops xml . Here is my code. How to show animation sliding down , when the visibility goes wrong?

1

There are 1 best solutions below

3
On

I have no explanation why it is not working with your current approach, but did you try to slide the Dialog into the screen using AnimatedVisibility functionality instead of animateDp? You can combine the fadeIn animation with slide animations using the + operator as explained in the documentation. A solution could look as follows, you might need to adjust it in some way:

AnimatedVisibility(
    visible = visibility,
    enter = fadeIn(
            animationSpec = keyframes {
                this.durationMillis = 200
            }
        ) + 
        slideInVertically(
            initialOffsetY = {
                it / 2
            }
        ),
    exit = fadeOut(
            animationSpec = keyframes {
                this.durationMillis = 200
            }
        ) + 
        slideOutVertically(
            targetOffsetY = {
                it / 2
            },
        )
    ),
    modifier = modifier
        .fillMaxSize()
        .zIndex(2f)
) {
    // ...
}

The initialOffset values are set to define from which direction the slide in or slide out should happen, as explained in this StackOverflow question.