如何在Flutter中创建符合示例样式的自定义日历?
自定义日历实现方案(匹配目标样式)
不用依赖第三方包,直接用原生HTML+CSS+JS就能实现你要的样式,以下是完整实现方案:
1. 基础HTML结构
先搭建日历的核心结构,包含年月控制区、星期表头、日期网格:
<div class="custom-calendar"> <div class="calendar-header"> <button class="nav-btn" id="prev-month"><</button> <h2 class="current-date" id="current-date"></h2> <button class="nav-btn" id="next-month">></button> </div> <div class="weekdays"> <div class="weekday">日</div> <div class="weekday">一</div> <div class="weekday">二</div> <div class="weekday">三</div> <div class="weekday">四</div> <div class="weekday">五</div> <div class="weekday">六</div> </div> <div class="calendar-grid" id="calendar-grid"></div> </div>
2. CSS样式定制
匹配示例里的视觉风格,包括选中高亮、周末样式、边框和间距:
.custom-calendar { max-width: 400px; margin: 20px auto; font-family: Arial, sans-serif; border: 1px solid #ddd; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .calendar-header { display: flex; justify-content: space-between; align-items: center; padding: 15px; background-color: #f5f5f5; } .nav-btn { background: none; border: none; font-size: 18px; cursor: pointer; padding: 5px 10px; border-radius: 4px; transition: background-color 0.2s; } .nav-btn:hover { background-color: #e0e0e0; } .current-date { margin: 0; font-size: 18px; font-weight: 600; } .weekdays { display: grid; grid-template-columns: repeat(7, 1fr); background-color: #f0f0f0; border-bottom: 1px solid #ddd; } .weekday { padding: 10px; text-align: center; font-weight: 500; font-size: 14px; } .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background-color: #ddd; } .calendar-day { padding: 12px; background-color: white; text-align: center; cursor: pointer; transition: background-color 0.2s; font-size: 14px; } .calendar-day.other-month { color: #ccc; } .calendar-day.weekend { color: #d9534f; } .calendar-day.selected { background-color: #0275d8; color: white; border-radius: 50%; } .calendar-day:hover { background-color: #f5f5f5; }
3. JS逻辑实现
处理日期计算、年月切换、选中交互:
let currentDate = new Date(); function renderCalendar() { const year = currentDate.getFullYear(); const month = currentDate.getMonth(); // 更新年月显示 document.getElementById('current-date').textContent = `${year}年${month + 1}月`; const firstDayOfMonth = new Date(year, month, 1); const lastDayOfMonth = new Date(year, month + 1, 0); const lastDayOfPrevMonth = new Date(year, month, 0); const daysInMonth = lastDayOfMonth.getDate(); const daysInPrevMonth = lastDayOfPrevMonth.getDate(); const startDay = firstDayOfMonth.getDay(); // 0=周日,6=周六 const calendarGrid = document.getElementById('calendar-grid'); calendarGrid.innerHTML = ''; // 添加上个月的剩余日期 for (let i = startDay - 1; i >= 0; i--) { const dayDiv = document.createElement('div'); dayDiv.classList.add('calendar-day', 'other-month'); dayDiv.textContent = daysInPrevMonth - i; calendarGrid.appendChild(dayDiv); } // 添加当月日期 for (let day = 1; day <= daysInMonth; day++) { const dayDiv = document.createElement('div'); dayDiv.classList.add('calendar-day'); dayDiv.textContent = day; // 标记周末 const dayOfWeek = new Date(year, month, day).getDay(); if (dayOfWeek === 0 || dayOfWeek === 6) { dayDiv.classList.add('weekend'); } // 标记今天 if (year === new Date().getFullYear() && month === new Date().getMonth() && day === new Date().getDate()) { dayDiv.classList.add('selected'); } // 点击选中日期 dayDiv.addEventListener('click', () => { document.querySelectorAll('.calendar-day.selected').forEach(el => el.classList.remove('selected')); dayDiv.classList.add('selected'); }); calendarGrid.appendChild(dayDiv); } // 添加下个月的补充日期 const totalCells = calendarGrid.children.length; const remainingCells = 42 - totalCells; // 6行*7列=42个格子 for (let day = 1; day <= remainingCells; day++) { const dayDiv = document.createElement('div'); dayDiv.classList.add('calendar-day', 'other-month'); dayDiv.textContent = day; calendarGrid.appendChild(dayDiv); } } // 年月切换按钮事件 document.getElementById('prev-month').addEventListener('click', () => { currentDate.setMonth(currentDate.getMonth() - 1); renderCalendar(); }); document.getElementById('next-month').addEventListener('click', () => { currentDate.setMonth(currentDate.getMonth() + 1); renderCalendar(); }); // 初始化日历 renderCalendar();
关键说明
- 完全自定义CSS,你可以根据示例图调整颜色、圆角、间距等细节,比如选中日期的背景色、周末文字颜色
- 原生JS逻辑无依赖,避免第三方包的样式限制
- 支持年月切换、日期选中、周末标记、跨月日期显示
内容的提问来源于stack exchange,提问作者Ãm̐ịť Śĩńğh Řâjpůť
相关产品推荐
相关产品推荐

