androidandroid-jetpack-composeandroid-motionlayout

How to align content with motion layout?


I have made a collapsible top app bar in jetpack compose using a motion layout. The app bar actually contains a box with a swipeable modifier and its anchors are mapped to swiping state COLLAPSED and EXPANDED. The problem is that the content which should align under the top app bar is actually being hidden under the top app bar when it is expanded.

Any suggestions of how could i constraint the content with the top app bar so the content changes its height according to the swipe state.

kotlin

@OptIn(ExperimentalMotionApi::class, ExperimentalMaterialApi::class)
@Composable
fun UserData(
    user: User
) {

    val swipingState = rememberSwipeableState(initialValue = SwipingStates.EXPANDED)
    val context = LocalContext.current
    val motionScene = remember {
        context.resources
            .openRawResource(R.raw.motion_scene)
            .readBytes()
            .decodeToString()
    }
    MotionLayout(
        progress =  if (swipingState.progress.to == SwipingStates.COLLAPSED) swipingState.progress.fraction
        else 1f - swipingState.progress.fraction,
        motionScene = MotionScene(content = motionScene),
        modifier = Modifier.fillMaxWidth()
    )
    {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(LightBlue)
                .layoutId("box")
                .swipeable(
                    state = swipingState,
                    thresholds = { _, _ -> FractionalThreshold(0.5f) },
                    orientation = Orientation.Vertical,
                    anchors = mapOf(
                        0f to SwipingStates.EXPANDED,
                        400f to SwipingStates.COLLAPSED,
                    )
                )
        )

    val painter = rememberAsyncImagePainter(
        model =
        ImageRequest
            .Builder(LocalContext.current)
            .data(user.imageUrl)
            .build()
    )
    Image(
        painter = painter,
        contentDescription = null,
        modifier = Modifier
            .clip(CircleShape)
            .border(2.dp, Color.White, CircleShape)
            .layoutId("profile_pic"),
        contentScale = ContentScale.Crop
    )

    Column(
        modifier = Modifier
            .layoutId("details"),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    )
    {
        Text(
            modifier = Modifier.padding(start = 13.dp),
            text = user.email,
            fontSize = 18.sp,
            color = Color.White
        )
        Spacer(modifier = Modifier.height(5.dp))
        Text(text = "Boards : ", fontSize = 18.sp, color = Color.White)
        Spacer(modifier = Modifier.height(5.dp))
        Text(text = "Cards : ", fontSize = 18.sp, color = Color.White)
        Spacer(modifier = Modifier.height(8.dp))
        androidx.compose.material3.Button(
            modifier = Modifier
                .width(110.dp)
                .padding(start = 10.dp),
            colors = ButtonDefaults.buttonColors(Color.Blue.copy(0.2f)),
            onClick = {

            }) {
            Text(text = "LogOut", color = Color.White)

        }

    }
    Text(
        text = user.userName,
        fontSize = 24.sp,
        color = Color.White,
        modifier = Modifier.layoutId("username")
    )
}
}

This is my composable which contains the motion layout.


Solution

  • I have solved the issue by putting the whole screen view inside the Box composable and managed the swipe using nestedScrollConnection. These are the link that helped me

    https://youtu.be/XS7G3iSVWNE

    and the github link mentioned in the above comment.