'Jetpack Compose BottomSheet
I have started to learn jetpack compose. I want to show bottomsheet in click of IconButton.But i got error @Composable invocations can only happen from the context of a @Composable function how I can implement this logic.
Here is code
@RequiresApi(Build.VERSION_CODES.O)
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun AddTaskScreen(navController: NavController) {
var taskTitle by remember { mutableStateOf("") }
val currentDate = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(Date())
var taskDescription by remember { mutableStateOf("") }
val taskDuration by remember { mutableStateOf(currentDate.toString()) }
val taskTypes = listOf("Urgent", "Medium", "High")
var expanded by remember { mutableStateOf(false) }
var selectedOptionText by remember { mutableStateOf(taskTypes[0]) }
val clickHandler: () -> Unit = {
DateBottomSheet()
}
Column() {
AppToolBar(title = "AddTaskScreen") {
navController.navigateUp()
}
OutlinedTextField(
value = taskTitle,
label = { Text(text = "Please input task title") },
onValueChange = { text -> taskTitle = text },
modifier = textFieldModifier
)
OutlinedTextField(
value = taskDescription,
label = { Text(text = "Please input task description") },
onValueChange = { text -> taskDescription = text },
modifier = textFieldModifier.height(200.dp)
)
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
expanded = !expanded
},
modifier = Modifier
.fillMaxWidth()
.padding(20.dp)
) {
OutlinedTextField(
readOnly = true,
value = selectedOptionText,
onValueChange = { },
label = { Text("Task priority") },
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(
expanded = expanded
)
},
modifier = Modifier.fillMaxWidth()
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
}
) {
taskTypes.forEach { selectionOption ->
DropdownMenuItem(
onClick = {
selectedOptionText = selectionOption
expanded = false
}
) {
Text(text = selectionOption)
}
}
}
}
//task time textField
OutlinedTextField(
value = taskDuration,
readOnly = true,
label = { Text(text = "Please select task duration") },
onValueChange = { text -> taskDescription = text },
modifier = textFieldModifier,
trailingIcon = {
IconButton(
onClick = {
clickHandler.invoke()
}) {
Icon(Icons.Filled.DateRange, contentDescription = "")
}
}
)
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun DateBottomSheet() {
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberBottomSheetState(
initialValue = BottomSheetValue.Collapsed
)
)
BottomSheetScaffold(
sheetContent = {
Column() {
Text(text = "ThisIsBottomSheet")
Text(text = "ThisIsBottomSheet")
Text(text = "ThisIsBottomSheet")
Text(text = "ThisIsBottomSheet")
Text(text = "ThisIsBottomSheet")
}
},
scaffoldState = bottomSheetScaffoldState
) {
}
But i got error @Composable invocations can only happen from the context of a @Composable function how I can implement this logic
Solution 1:[1]
You can simply use mutabelState for handling your button click event to show Bottom Sheet.
You can do following changes ->
@RequiresApi(Build.VERSION_CODES.O)
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun AddTaskScreen(navController: NavController) {
var taskTitle by remember { mutableStateOf("") }
val currentDate = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(Date())
var taskDescription by remember { mutableStateOf("") }
val taskDuration by remember { mutableStateOf(currentDate.toString()) }
val taskTypes = listOf("Urgent", "Medium", "High")
var expanded by remember { mutableStateOf(false) }
var selectedOptionText by remember { mutableStateOf(taskTypes[0]) }
var openBottomSheet by rememberSaveable { mutableStateOf(false) }
Column() {
AppToolBar(title = "AddTaskScreen") {
navController.navigateUp()
}
OutlinedTextField(
value = taskTitle,
label = { Text(text = "Please input task title") },
onValueChange = { text -> taskTitle = text },
modifier = textFieldModifier
)
OutlinedTextField(
value = taskDescription,
label = { Text(text = "Please input task description") },
onValueChange = { text -> taskDescription = text },
modifier = textFieldModifier.height(200.dp)
)
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = {
expanded = !expanded
},
modifier = Modifier
.fillMaxWidth()
.padding(20.dp)
) {
OutlinedTextField(
readOnly = true,
value = selectedOptionText,
onValueChange = { },
label = { Text("Task priority") },
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(
expanded = expanded
)
},
modifier = Modifier.fillMaxWidth()
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
}
) {
taskTypes.forEach { selectionOption ->
DropdownMenuItem(
onClick = {
selectedOptionText = selectionOption
expanded = false
}
) {
Text(text = selectionOption)
}
}
}
}
//task time textField
OutlinedTextField(
value = taskDuration,
readOnly = true,
label = { Text(text = "Please select task duration") },
onValueChange = { text -> taskDescription = text },
modifier = textFieldModifier,
trailingIcon = {
IconButton(
onClick = {
openBottomSheet = true
}) {
Icon(Icons.Filled.DateRange, contentDescription = "")
}
}
)
if (openBottomSheet) {
DateBottomSheet()
}
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun DateBottomSheet() {
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberBottomSheetState(
initialValue = BottomSheetValue.Collapsed
)
)
BottomSheetScaffold(
sheetContent = {
Column() {
Text(text = "ThisIsBottomSheet")
Text(text = "ThisIsBottomSheet")
Text(text = "ThisIsBottomSheet")
Text(text = "ThisIsBottomSheet")
Text(text = "ThisIsBottomSheet")
}
},
scaffoldState = bottomSheetScaffoldState
) {
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |

