You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:27:00