自定义仿日历组件弹框

自定义仿日历组件弹框

可以选择区间,不区分点击日期前后,添加简易版阳历转农历,从第三方免费接口获取节假日,定义扩展定义排班信息标签

创建LunarCalendarDialog底部弹框

typescript 复制代码
class LunarCalendarDialog(
    context: Context,
    private val listener: OnDateRangeSelectedListener,
    private val initialStartDate: Date? = null,
    private val initialEndDate: Date? = null,
    private var holidayData: Map<String, HolidayInfo>? = null,
    private val scheduleData: Map<String, ScheduleInfo>? = null,
)
scss 复制代码
     // 启动协程获取当年节假日数据
        CoroutineScope(Dispatchers.Main).launch {
            val year = Calendar.getInstance().get(Calendar.YEAR)
            val fetchedHolidays = try {
                val fetchedHolidays = LunarCalendarNetUtil.fetchYearHolidayMap(year)
//                val fetchedNextYearHolidays = LunarCalendarNetUtil.fetchYearHolidayMap(year + 1)
//                fetchedHolidays + fetchedNextYearHolidays
                fetchedHolidays
            } catch (e: Exception) {
                e.printStackTrace()
                mutableMapOf<String, LunarCalendarDialog.HolidayInfo>()
            }
            holidayData = fetchedHolidays // 更新节假日数据
            initMonthsData() // 重新初始化月份数据,应用新的节假日
            monthsAdapter.notifyDataSetChanged() // 刷新UI
        }

通过LunarCalendarNetUtil获取节假日数据

kotlin 复制代码
private const val HOLIDAY_API_URL = "https://timor.tech/api/holiday/year/"
kotlin 复制代码
private fun parseHolidayResponse(json: String): Map<String, LunarCalendarDialog.HolidayInfo> {
    val holidayMap = mutableMapOf<String, LunarCalendarDialog.HolidayInfo>()
    val jsonObject = JSONObject(json)

    // 检查接口返回状态(code=0 表示成功)
    if (jsonObject.getInt("code") == 0) {
       val data = jsonObject.getJSONObject("holiday")
        data.keys().forEachRemaining { key ->
            val dayObj = data.getJSONObject(key)
            val date = dayObj.getString("date") // 格式:yyyy-MM-dd
            val name = dayObj.getString("name")
            val isHoliday = dayObj.getBoolean("holiday") // 是否为法定节假日
            holidayMap[date] = LunarCalendarDialog.HolidayInfo(name, isHoliday)
        }
    } else {
        Log.e(TAG, "接口返回错误:${jsonObject.getString("msg")}")
    }
    return holidayMap
}

通过LunarConverter工具获取阳历日期对应的农历日期,也可以寻找其他库替代

kotlin 复制代码
fun getLunarDateString(calendar: Calendar): String {
    val year = calendar.get(Calendar.YEAR)
    val month = calendar.get(Calendar.MONTH) + 1 // 注意Calendar的月份是从0开始的
    val day = calendar.get(Calendar.DAY_OF_MONTH)
    println("今天阳历是: $year 年$month 月$day 日")
    val lunarDate = solarToLunar(year, month, day)
    println("对应的农历是: $lunarDate")
    val lunarDateArrayEnd = lunarDate.split(" ")[1]
    val dayName = lunarDateArrayEnd.substring(lunarDateArrayEnd.indexOf("月") + 1)
    if (dayName == "初一") {
        return lunarDateArrayEnd.substring(0, lunarDateArrayEnd.indexOf("月") + 1)
    }
    return dayName
}

使用方法

kotlin 复制代码
// 获取排班数据
        val scheduleData = mapOf(
            "2026-01-05" to LunarCalendarDialog.ScheduleInfo("早班", "08:00-16:00"),
            "2026-01-06" to LunarCalendarDialog.ScheduleInfo("中班", "16:00-24:00"),
            // 更多排班数据...
        )

// 显示日历弹窗
        val dialog = LunarCalendarDialog(
            context = this,
            listener = object : LunarCalendarDialog.OnDateRangeSelectedListener {
                override fun onDateRangeSelected(startDate: Date, endDate: Date) {
                    // 处理选择的日期范围
                    val format = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
                    Toast.makeText(
                        this@MainActivity,
                        "开始日期: ${format.format(startDate)}\n结束日期: ${format.format(endDate)}",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            },
            scheduleData = scheduleData
        )
        findViewById<MaterialButton>(R.id.calendar_button).setOnClickListener {
            dialog.show()
        }

展示效果

源码地址

CalendarDemo: 日历区间选择

相关推荐
Android轮子哥16 分钟前
尝试解决 Android 适配最后一公里
android
雨白1 小时前
OkHttp 源码解析:enqueue 非同步流程与 Dispatcher 调度
android
没有了遇见2 小时前
Android 外接 U 盘开发实战:从权限到文件复制
android
Monkey-旭3 小时前
Android 文件存储机制全解析
android·文件存储·kolin
zhangphil4 小时前
Android Coil 3拦截器Interceptor计算单次请求耗时,Kotlin
android·kotlin
DokiDoki之父4 小时前
多线程—飞机大战排行榜功能(2.0版本)
android·java·开发语言
用户2018792831676 小时前
强制关闭生命周期延时的Activity实现思路
android
用户2018792831676 小时前
Activity后生命周期暂停问题
android
用户2018792831676 小时前
浅析:WindowManager添加的 View 的事件传递机制
android