节日改为只在当天显示,休/班改为右上角角标

之前法定假期的「春节休」之类文本占据了整段假期,把假期里出现
的节气(雨水、惊蛰等)和其他节日全部挤掉。现在拆成两条线:

- 主标注:按 农历节日 → 节气当天 → 公历节日 → 农历日期 的
  优先级,仅在节日/节气当天展示节日名。
- 右上角角标:单独读取法定假期标志,调休「休」为 error 色,
  调休「班」为 primary 色;非当月时整体降低不透明度。

DayCell 外层多包一层 Box 承载 aspectRatio,原内层保留圆形裁
剪与涟漪;角标放在外层 TopEnd,避免被 CircleShape 裁掉。
This commit is contained in:
meyou 2026-05-16 17:34:53 +08:00
parent 889a54db0e
commit c28eb8d0e5

View File

@ -9,7 +9,9 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@ -25,6 +27,7 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@ -113,18 +116,18 @@ fun DayCell(
data class DayAnnotation(val text: String, val isHighlight: Boolean)
val holidayBadge = remember(date) {
@Suppress("DEPRECATION") // monthNumber 无替代 API
val solarDay = SolarDay.fromYmd(date.year, date.monthNumber, date.day)
solarDay.getLegalHoliday()?.let { if (it.isWork()) "" else "" }
}
val annotation = remember(date) {
@Suppress("DEPRECATION") // monthNumber 无替代 API
val solarDay = SolarDay.fromYmd(date.year, date.monthNumber, date.day)
val lunarDay = solarDay.getLunarDay()
// 法定假日优先
val legalHoliday = solarDay.getLegalHoliday()
if (legalHoliday != null) {
val suffix = if (legalHoliday.isWork()) "" else ""
return@remember DayAnnotation("${legalHoliday.getName()}$suffix", true)
}
// 农历传统节日
// 农历传统节日(仅当天)
val lunarFestival = lunarDay.getFestival()
if (lunarFestival != null) {
return@remember DayAnnotation(lunarFestival.getName(), true)
@ -136,7 +139,7 @@ fun DayCell(
return@remember DayAnnotation(termDay.getSolarTerm().getName(), true)
}
// 公历节日
// 公历节日(仅当天)
val solarFestival = solarDay.getFestival()
if (solarFestival != null) {
return@remember DayAnnotation(solarFestival.getName(), true)
@ -176,52 +179,75 @@ fun DayCell(
}
}
val holidayBadgeColor = when (holidayBadge) {
"" -> MaterialTheme.colorScheme.error
"" -> MaterialTheme.colorScheme.primary
else -> Color.Transparent
}
val holidayBadgeAlpha = if (isCurrentMonth) 1f else 0.38f
Box(
modifier = modifier
.aspectRatio(1f)
.semantics {
@Suppress("DEPRECATION")
contentDescription = "${date.year}${date.monthNumber}${date.day}"
}
.clip(CircleShape)
.drawBehind {
if (revealProgress > 0f) {
val maxRadius = size.minDimension / 2f
drawCircle(
color = selectedColor,
radius = revealProgress * maxRadius,
center = Offset(size.width / 2f, size.height / 2f)
)
}
if (borderAlpha > 0f) {
drawCircle(
color = todayBorderColor.copy(alpha = borderAlpha.coerceAtMost(1f)),
radius = size.minDimension / 2f,
center = Offset(size.width / 2f, size.height / 2f),
style = Stroke(width = borderAlpha.coerceAtMost(1.5f) * 1.5.dp.toPx())
)
}
}
.clickable(onClick = onClick),
contentAlignment = Alignment.Center
modifier = modifier.aspectRatio(1f)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
Box(
modifier = Modifier
.fillMaxSize()
.semantics {
@Suppress("DEPRECATION")
contentDescription = "${date.year}${date.monthNumber}${date.day}"
}
.clip(CircleShape)
.drawBehind {
if (revealProgress > 0f) {
val maxRadius = size.minDimension / 2f
drawCircle(
color = selectedColor,
radius = revealProgress * maxRadius,
center = Offset(size.width / 2f, size.height / 2f)
)
}
if (borderAlpha > 0f) {
drawCircle(
color = todayBorderColor.copy(alpha = borderAlpha.coerceAtMost(1f)),
radius = size.minDimension / 2f,
center = Offset(size.width / 2f, size.height / 2f),
style = Stroke(width = borderAlpha.coerceAtMost(1.5f) * 1.5.dp.toPx())
)
}
}
.clickable(onClick = onClick),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = date.day.toString(),
textAlign = TextAlign.Center,
color = contentColor,
style = MaterialTheme.typography.bodyMedium
)
Text(
text = annotation.text,
textAlign = TextAlign.Center,
color = lunarColor,
fontSize = 7.sp,
maxLines = 1,
overflow = TextOverflow.Clip,
lineHeight = 9.sp
)
}
}
if (holidayBadge != null) {
Text(
text = date.day.toString(),
textAlign = TextAlign.Center,
color = contentColor,
style = MaterialTheme.typography.bodyMedium
)
Text(
text = annotation.text,
textAlign = TextAlign.Center,
color = lunarColor,
fontSize = 7.sp,
maxLines = 1,
overflow = TextOverflow.Clip,
lineHeight = 9.sp
text = holidayBadge,
color = holidayBadgeColor.copy(alpha = holidayBadgeAlpha),
fontSize = 9.sp,
fontWeight = FontWeight.Bold,
lineHeight = 9.sp,
modifier = Modifier
.align(Alignment.TopEnd)
.padding(top = 2.dp, end = 4.dp)
)
}
}