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

Android Jetpack Compose中如何在DatePickerDialog显示回历?

在Jetpack Compose DatePickerDialog中显示回历日期(无第三方库)

Android官方提供原生API支持回历(希吉来历),无需依赖第三方库,可通过以下方案实现:

核心依赖类

  • API 26+:使用Java 8时间API中的java.time.chrono.HijrahDate和HijrahChronology
  • API <26:使用Android ICU库的android.icu.util.HijrahCalendar(需引入官方兼容依赖)

完整实现代码

API 26+ 版本

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.DatePickerFormatter
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.tooling.preview.Preview
import java.time.LocalDate
import java.time.ZoneId
import java.time.chrono.HijrahChronology
import java.time.chrono.HijrahDate
import java.time.format.TextStyle
import java.util.Locale

@Composable
fun HijriDatePicker(
    onDateSelected: (HijrahDate) -> Unit,
    onDismiss: () -> Unit
) {
    val hijrahChronology = HijrahChronology.INSTANCE
    val todayHijri = HijrahDate.now()
    val selectedHijriDate = remember { mutableStateOf(todayHijri) }
    // 将回历日期转换为ISO日历的LocalDate,适配DatePicker的默认逻辑
    val selectedIsoDate = selectedHijriDate.value.atZone(ZoneId.systemDefault()).toLocalDate()

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                onDateSelected(selectedHijriDate.value)
                onDismiss()
            }) {
                Text("确认")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("取消")
            }
        }
    ) {
        DatePicker(
            selectedDate = selectedIsoDate,
            onDateChange = { isoDate ->
                // 将选中的ISO日期转换回回历日期
                selectedHijriDate.value = hijrahChronology.date(isoDate)
            },
            // 自定义日期显示格式,完全展示回历的年/月/日
            dateFormatter = remember {
                DatePickerFormatter(
                    yearFormatter = { isoDate ->
                        "${hijrahChronology.date(isoDate).year}"
                    },
                    monthFormatter = { isoDate ->
                        hijrahChronology.date(isoDate).month.getDisplayName(
                            TextStyle.FULL,
                            Locale.getDefault()
                        )
                    },
                    dayFormatter = { isoDate ->
                        "${hijrahChronology.date(isoDate).dayOfMonth}"
                    }
                )
            }
        )
    }
}

// 预览示例
@Preview
@Composable
fun PreviewHijriDatePicker() {
    Column {
        TextButton(onClick = {}) {
            Text("打开回历选择器")
        }
    }
}

低版本兼容方案(API <26)

如果需要兼容Android 8.0以下版本,需在build.gradle中添加官方兼容依赖:

dependencies {
    implementation "androidx.core:core-icu4j:1.12.0"
}

然后使用android.icu.util.HijrahCalendar进行日期转换,核心逻辑类似,只需将HijrahDate替换为HijrahCalendar的日期处理逻辑。

关键说明

  • 时区适配:建议指定回历常用时区(如ZoneId.of("Asia/Riyadh")),避免时区转换误差
  • 格式自定义:通过DatePickerFormatter可以完全控制日期选择器的显示文本,确保展示的是回历的年月信息
  • 日期转换:由于Compose的DatePicker默认基于ISO公历,需要在回历和公历间做双向转换,保证选中日期的准确性

内容的提问来源于stack exchange,提问作者Josss

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:02:08