Jetpack Compose点击按钮打开DatePicker并解决@Composable调用报错
问题原因
@Composable函数只能在Compose重组的上下文环境中调用,而图标onClick的回调属于普通的非Composable作用域,你直接在onClick里调用DatePicker就会触发这个报错。同时你之前直接在Row中写DatePicker的写法也是错误的,会导致页面一加载就弹出日期选择器,不符合点击图标才弹出的需求。
解决方案
核心逻辑是新增状态变量控制日期选择器的显隐:点击图标仅修改状态值,DatePicker本身在Composable作用域内根据状态判断是否渲染。
修正后的WeightData完整代码
@ExperimentalComposeUiApi @Composable fun WeightData(viewModel: AddWeightViewModel) { // 新增控制日期选择器显隐的状态 val showDatePicker = remember { mutableStateOf(false) } val dateFormatter = remember { DateTimeFormatter.ofPattern("MMM d, YYYY") } val keyboardController = LocalSoftwareKeyboardController.current Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(22.dp), modifier = Modifier .drawBehind { drawCircle( color = textColor, radius = 450f, style = Stroke(width = 1.dp.toPx()) ) } ) { Text(text = "Enter Weight", color = Color.White.copy(alpha = .8f)) TextField( value = viewModel.weightState.value, onValueChange = { viewModel.onWeightChange(it) }, modifier = Modifier.background(color = MaterialTheme.colors.primary), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done), keyboardActions = KeyboardActions(onDone = { keyboardController?.hide() }), singleLine = true ) Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { Icon( imageVector = Icons.Default.DateRange, contentDescription = "选择日期", modifier = Modifier.clickable { // 点击仅修改显隐状态,不直接调用Composable函数 showDatePicker.value = true } ) Spacer(modifier = Modifier.width(20.dp)) // 展示选中的日期文本 Text( text = viewModel.dateState.value.ifEmpty { "请选择日期" }, color = Color.White ) } } // 日期选择器在Composable作用域内,根据状态判断是否渲染 if (showDatePicker.value) { DatePicker( onDateSelected = { selectedDate -> // 选中日期后更新ViewModel的状态 viewModel.onDateChange(selectedDate.format(dateFormatter)) }, onDismissRequest = { // 关闭选择器时更新显隐状态 showDatePicker.value = false } ) } }
额外优化建议
- 你当前CustomCalendarView中构建LocalDate的逻辑可以优化,避免日期异常:
把
LocalDate.now().withMonth(month + 1).withYear(year).withDayOfMonth(dayOfMonth)
替换为
LocalDate.of(year, month + 1, dayOfMonth)
- DatePicker中Cancel和OK按钮的颜色设置有误,当前用了
onPrimary颜色,在浅色surface背景下会看不清,建议替换为MaterialTheme.colors.primary
内容的提问来源于stack exchange,提问作者Ashish Gautam
相关产品推荐
相关产品推荐

