如何实现含三个RecyclerView的联动日历并填充年月数据?
实现三联动日历RecyclerView:数据填充与交互指南
Hey there! 我来一步步帮你搞定这三个RecyclerView的数据源设置和联动逻辑,其实核心就是固定年份/月份列表 + 动态生成日期列表,再配合选中事件的刷新就行。
一、先搞定基础数据源
1. 年份列表
你可以自定义年份范围,比如最近15年或者用户需要的区间,直接用循环生成就行:
// Java 示例:生成2010-2025的年份列表 List<Integer> yearList = new ArrayList<>(); for (int year = 2010; year <= 2025; year++) { yearList.add(year); }
// Kotlin 示例 val yearList = (2010..2025).toList()
把这个列表传给年份RecyclerView的Adapter就OK了。
2. 月份列表
月份可以是数字(1-12)或者带文字的("1月"到"12月"),按需选择:
// Java:中文月份列表 List<String> monthList = Arrays.asList("1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"); // 或者数字月份 List<Integer> monthNumList = IntStream.rangeClosed(1, 12).boxed().collect(Collectors.toList());
// Kotlin:中文月份列表 val monthList = listOf("1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月") // 数字月份 val monthNumList = (1..12).toList()
同样把这个列表绑定给月份RecyclerView的Adapter。
3. 日期列表(联动核心)
日期是依赖选中的年份和月份的,不能提前固定,得动态计算当月的天数来生成列表。推荐用Java 8+的LocalDate(或者AndroidX的ThreeTenABP兼容低版本),比传统Calendar好用太多:
动态生成日期的工具方法
// Java:传入选中的年、月,返回当月的日期列表(1到当月天数) public List<Integer> generateDayList(int selectedYear, int selectedMonth) { List<Integer> dayList = new ArrayList<>(); // LocalDate的月份是1-based,和我们的数字月份对应 LocalDate monthStart = LocalDate.of(selectedYear, selectedMonth, 1); int totalDays = monthStart.lengthOfMonth(); for (int day = 1; day <= totalDays; day++) { dayList.add(day); } return dayList; }
// Kotlin 版本 fun generateDayList(selectedYear: Int, selectedMonth: Int): List<Int> { val monthStart = LocalDate.of(selectedYear, selectedMonth, 1) val totalDays = monthStart.lengthOfMonth() return (1..totalDays).toList() }
二、实现联动逻辑
现在要让年份/月份的选中事件触发日期列表的刷新,核心就是监听RecyclerView的item点击,更新选中的年月,然后重新生成日期列表并刷新日期RecyclerView。
1. 年份RecyclerView的点击监听
在年份Adapter的onBindViewHolder里给item设置点击事件:
// Java 示例 yearViewHolder.itemView.setOnClickListener(v -> { // 获取选中的年份 int currentSelectedYear = yearList.get(position); // 保存全局选中年份(比如在Activity/Fragment里定义变量) mSelectedYear = currentSelectedYear; // 重新生成日期列表,用当前选中的月份(默认可以设为1,或者之前选中的月份) List<Integer> newDayList = generateDayList(mSelectedYear, mSelectedMonth); // 刷新日期Adapter mDayAdapter.submitList(newDayList); // 如果用ListAdapter的话用submitList,否则用notifyDataSetChanged });
2. 月份RecyclerView的点击监听
和年份逻辑类似,注意如果用的是中文月份,要先转成数字:
// Java 示例:如果是中文月份列表 monthViewHolder.itemView.setOnClickListener(v -> { String monthStr = monthList.get(position); // 把"1月"转成数字1 int currentSelectedMonth = Integer.parseInt(monthStr.replace("月", "")); mSelectedMonth = currentSelectedMonth; // 生成新日期列表 List<Integer> newDayList = generateDayList(mSelectedYear, mSelectedMonth); mDayAdapter.submitList(newDayList); });
三、初始化与细节优化
- 初始状态:打开页面时默认选中当前年月,生成对应的日期列表:
// Java 初始化示例 LocalDate now = LocalDate.now(); mSelectedYear = now.getYear(); mSelectedMonth = now.getMonthValue(); List<Integer> initialDayList = generateDayList(mSelectedYear, mSelectedMonth); mDayAdapter.submitList(initialDayList);
- 选中高亮:记得在每个Adapter里维护选中位置的变量,在
onBindViewHolder里更新item的UI(比如改变背景色、文字颜色),让用户知道当前选中的是哪一项。 - 性能优化:用
ListAdapter配合DiffUtil来刷新日期列表,比直接调用notifyDataSetChanged更高效,避免不必要的视图重绘。
这样一套下来,三个RecyclerView的数据源填充和联动就完全搞定啦~
内容的提问来源于stack exchange,提问作者DevMobApp




