feat: 底部卡片展示选中日期的相对天数、公历与农历信息

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-19 11:11:53 +08:00
parent 39bb2301d3
commit 0d58be45bc
3 changed files with 100 additions and 2 deletions

View File

@ -2,27 +2,42 @@ package plus.rua.project.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectVerticalDragGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.datetime.LocalDate
import plus.rua.project.CalendarViewModel
/**
* 底部卡片折叠状态下支持垂直拖拽触发折叠动画
*
* 卡片顶部显示拖拽把手下方展示选中日期信息
* 左侧为相对今天的天数描述A和公历日期B
* 右侧为农历日期C
*
* @param viewModel 日历 ViewModel用于读取折叠状态和驱动拖拽
* @param selectedDate 当前选中的日期
* @param today 今天的日期
* @param dragRangePx 拖拽手势映射范围像素progress 01 对应手指移动此距离
* 应设为折叠时日历实际高度变化量 (weeks-1)×rowHeight使拖拽跟手
* @param modifier 外部布局修饰符
@ -30,10 +45,16 @@ import plus.rua.project.CalendarViewModel
@Composable
fun BottomCard(
viewModel: CalendarViewModel,
selectedDate: LocalDate,
today: LocalDate,
dragRangePx: Float,
modifier: Modifier = Modifier
) {
val density = LocalDensity.current
val relativeDesc = relativeDayDescription(selectedDate, today)
@Suppress("DEPRECATION") // monthNumber 无替代 APIkotlinx-datetime 尚未提供新接口
val solarDesc = "${selectedDate.monthNumber}${selectedDate.day}"
val lunarDesc = formatLunarDate(selectedDate)
Surface(
modifier = modifier
@ -80,16 +101,52 @@ fun BottomCard(
color = MaterialTheme.colorScheme.surfaceVariant,
shadowElevation = 4.dp
) {
Box(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.fillMaxSize()) {
// 拖拽把手
Box(
modifier = Modifier
.align(Alignment.TopCenter)
.padding(top = 8.dp, bottom = 8.dp)
.clip(RoundedCornerShape(2.dp))
.background(MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f))
.fillMaxWidth(0.15f)
.height(4.dp)
.align(Alignment.CenterHorizontally)
)
Spacer(modifier = Modifier.height(8.dp))
// A / B / C 信息行
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
// 左侧A相对天数和 B公历日期在同一行
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = relativeDesc,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
fontSize = 14.sp
)
Spacer(modifier = Modifier.width(6.dp))
Text(
text = solarDesc,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
fontSize = 14.sp
)
}
// 右侧C农历日期
Text(
text = lunarDesc,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
fontSize = 14.sp
)
}
}
}
}

View File

@ -311,6 +311,8 @@ fun CalendarMonthView(
if (cardHeightPx > 0) {
BottomCard(
viewModel = viewModel,
selectedDate = viewModel.selectedDate,
today = today,
dragRangePx = dragRangePx,
modifier = Modifier
.fillMaxWidth()

View File

@ -1,7 +1,9 @@
package plus.rua.project.ui
import com.tyme.solar.SolarDay
import kotlinx.datetime.DatePeriod
import kotlinx.datetime.LocalDate
import kotlinx.datetime.daysUntil
import kotlinx.datetime.minus
import kotlinx.datetime.number
import kotlinx.datetime.plus
@ -130,3 +132,40 @@ fun pageToWeekMonday(page: Int, initial: LocalDate): LocalDate {
val offset = page - START_PAGE
return initial.plus(DatePeriod(days = offset * 7))
}
/**
* 计算选中日期相对于今天的天数描述
*
* 例如今天 19 选中 18 日返回"昨天"17 日返回"2天前"
* 20 日返回"明天"21 日返回"2天后"选中当天返回"今天"
*
* @param selectedDate 选中日期
* @param today 今天日期
* @return 相对天数描述
*/
fun relativeDayDescription(selectedDate: LocalDate, today: LocalDate): String {
val diff = today.daysUntil(selectedDate)
return when {
diff == 0 -> "今天"
diff == -1 -> "昨天"
diff == 1 -> "明天"
diff < 0 -> "${-diff}天前"
else -> "${diff}天后"
}
}
/**
* 将公历日期格式化为农历日期字符串
*
* 格式为"农历{月}{日}"例如"农历四月初三"
*
* @param date 公历日期
* @return 农历日期描述
*/
@Suppress("DEPRECATION") // monthNumber 无替代 APIkotlinx-datetime 尚未提供新接口
fun formatLunarDate(date: LocalDate): String {
val solarDay = SolarDay.fromYmd(date.year, date.monthNumber, date.day)
val lunarDay = solarDay.getLunarDay()
val lunarMonth = lunarDay.getLunarMonth()
return "农历${lunarMonth.getName()}${lunarDay.getName()}"
}