androidkotlinandroid-jetpack-composetextfieldmodalbottomsheet

Jetpack Compose: ModalBottomSheet Not Animating Smoothly


I'm working on a Jetpack Compose project and using the ModalBottomSheet from Material3 to display a bottom sheet when a FloatingActionButton is clicked. However, I'm experiencing issues with the sheet not animating smoothly when it appears or disappears. The animation seems to lag or isn't as fluid as expected.

Here's a summary of what I'm doing:

I have a MainScreen composable where the sheet visibility is controlled by a Boolean state. When the state is true, a custom bottom sheet (MyBottomSheet) is shown. The bottom sheet contains a TextField, and I'm trying to automatically focus on it when the sheet appears. The ModalBottomSheet is using a rememberModalBottomSheetState to manage its state. Despite following the standard implementation, the animation isn't smooth. I would greatly appreciate any advice on what might be causing this issue or how to improve the smoothness of the animations.

MyTextField.kt

@Composable
fun MyTextField(modifier: Modifier = Modifier) {
var text by remember { mutableStateOf("") }
val focusRequester = remember { FocusRequester() }

TextField(
    value = text,
    onValueChange = { text = it },
    label = { Text("Label") },
    modifier = modifier
        .fillMaxWidth()
        .focusRequester(focusRequester)
)

LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}
}

MyBottomSheet.kt

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyBottomSheet(modifier: Modifier, onDismiss: () -> Unit) {
val modalBottomSheetState = rememberModalBottomSheetState()
val coroutineScope = rememberCoroutineScope()

LaunchedEffect(modalBottomSheetState.isVisible) {
    if (modalBottomSheetState.isVisible) {
        coroutineScope.launch {
            modalBottomSheetState.show()
        }
    }
}

ModalBottomSheet(
    onDismissRequest = { onDismiss() },
    sheetState = modalBottomSheetState,
    dragHandle = { BottomSheetDefaults.DragHandle() },
    modifier = modifier,
    content = {
        MyTextField()
    }
)
}

MainScreen.kt

@Preview(showBackground = true)
@Composable
fun MainScreen() {
var showSheet by remember { mutableStateOf(false) }

if (showSheet) {
    MyBottomSheet(modifier = Modifier) {
        showSheet = false
    }
}
Box(
    modifier = Modifier
        .padding(all = 8.dp)
        .fillMaxSize()
) {
    MyFloatingActionButton(
        onClick = {
            showSheet = true

        },
        modifier = Modifier
            .align(Alignment.BottomEnd)
            .padding(bottom = 80.dp)
            .padding(end = 10.dp)
    )
}
}

Solution

  • I'm not sure if these changes will fix the issue because you didn't provide a complete example to test.

    Since you're already controlling the bottom sheet's visibility with a state variable, you don't need to do it programmatically as well. You can remove or comment out that part of the code, like this:

    @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun MyBottomSheet(modifier: Modifier, onDismiss: () -> Unit) {
        val modalBottomSheetState = rememberModalBottomSheetState()
    //    val coroutineScope = rememberCoroutineScope()
    //
    //    LaunchedEffect(modalBottomSheetState.isVisible) {
    //        if (modalBottomSheetState.isVisible) {
    //            coroutineScope.launch {
    //                modalBottomSheetState.show()
    //            }
    //        }
    //    }
    
        ModalBottomSheet(
            onDismissRequest = { onDismiss() },
            sheetState = modalBottomSheetState,
            //dragHandle = { BottomSheetDefaults.DragHandle() }, // Not needed, this is the default value
            modifier = modifier,
            content = {
                MyTextField()
            }
        )
    }
    

    Another option to try is removing the auto-focus on the TextField. That might be causing the animation issue.

    I hope this helps fix the problem.