feat: 年视图标题栏改为农历干支年份+「今年」按钮,移除箭头导航

- YearHeader 从 Row 改为 Column 布局
- 移除左右箭头年份切换,改为横向滑动翻页
- 添加农历干支+生肖年显示(如「丙午马年」)
- 非当前年份时显示「今年」按钮,点击快速返回今年
- 同步移除 AppInfo.VERSION(已由动态版本号替代)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-20 01:28:36 +08:00
parent 841a186e0f
commit 5d038932d9
3 changed files with 59 additions and 29 deletions

View File

@ -5,5 +5,4 @@ package plus.rua.project
*/ */
object AppInfo { object AppInfo {
const val NAME = "鸭鸭日历" const val NAME = "鸭鸭日历"
const val VERSION = "1.0"
} }

View File

@ -225,6 +225,7 @@ fun CalendarMonthView(
) { ) {
YearHeader( YearHeader(
year = viewModel.yearViewYear, year = viewModel.yearViewYear,
currentYear = today.year,
onYearChange = { newYear -> onYearChange = { newYear ->
val offset = newYear - viewModel.yearViewYear val offset = newYear - viewModel.yearViewYear
val targetPage = yearPagerState.currentPage + offset val targetPage = yearPagerState.currentPage + offset

View File

@ -1,6 +1,7 @@
package plus.rua.project.ui package plus.rua.project.ui
import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.slideOutVertically
@ -8,23 +9,25 @@ import androidx.compose.animation.togetherWith
import androidx.compose.foundation.Canvas import androidx.compose.foundation.Canvas
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText import androidx.compose.ui.text.drawText
@ -32,6 +35,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.tyme.lunar.LunarYear
import kotlinx.datetime.DatePeriod import kotlinx.datetime.DatePeriod
import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDate
import kotlinx.datetime.minus import kotlinx.datetime.minus
@ -303,37 +307,28 @@ private fun generateMiniMonthDays(year: Int, month: Int): List<MiniDayData> {
} }
/** /**
* 年视图标题栏显示年份文字和左右导航箭头 * 年视图标题栏左侧显示年份文字与农历干支年右侧在非今年时显示今年按钮
* *
* 年份切换时文字有垂直滑动过渡动画方向由新旧年份大小决定 * 年份切换时年份与农历年文字有垂直滑动过渡动画
* *
* @param year 当前年份 * @param year 当前年份
* @param currentYear 今年年份
* @param onYearChange 年份切换回调 * @param onYearChange 年份切换回调
* @param modifier 外部布局修饰符 * @param modifier 外部布局修饰符
*/ */
@Composable @Composable
fun YearHeader( fun YearHeader(
year: Int, year: Int,
currentYear: Int,
onYearChange: (Int) -> Unit, onYearChange: (Int) -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Row( Column(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp), .padding(vertical = 8.dp, horizontal = 12.dp)
verticalAlignment = Alignment.CenterVertically
) { ) {
Text( Row(verticalAlignment = Alignment.CenterVertically) {
text = "",
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier
.clip(CircleShape)
.clickable { onYearChange(year - 1) }
.padding(horizontal = 16.dp, vertical = 8.dp)
)
Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.Center) {
AnimatedContent( AnimatedContent(
targetState = year, targetState = year,
transitionSpec = { transitionSpec = {
@ -353,16 +348,51 @@ fun YearHeader(
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
} }
} Spacer(modifier = Modifier.weight(1f))
val showThisYear = year != currentYear
val thisYearAlpha by animateFloatAsState(
targetValue = if (showThisYear) 1f else 0f,
animationSpec = tween(200)
)
Text( Text(
text = "", text = "今年",
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
fontSize = 14.sp,
modifier = Modifier modifier = Modifier
.clip(CircleShape) .graphicsLayer { alpha = thisYearAlpha }
.clickable { onYearChange(year + 1) } .clip(RoundedCornerShape(12.dp))
.padding(horizontal = 16.dp, vertical = 8.dp) .clickable(enabled = showThisYear) { onYearChange(currentYear) }
.padding(horizontal = 10.dp, vertical = 4.dp)
) )
} }
AnimatedContent(
targetState = year,
transitionSpec = {
if (targetState > initialState) {
slideInVertically(tween(250)) { -it } togetherWith
slideOutVertically(tween(250)) { it }
} else {
slideInVertically(tween(250)) { it } togetherWith
slideOutVertically(tween(250)) { -it }
}
},
modifier = Modifier.padding(top = 4.dp)
) { y ->
Text(
text = lunarYearLabel(y),
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6f),
style = MaterialTheme.typography.bodySmall
)
}
}
}
/**
* 返回类似丙午马年的农历干支生肖年标签
*/
private fun lunarYearLabel(year: Int): String {
val sixtyCycle = LunarYear.fromYear(year).getSixtyCycle()
val ganZhi = sixtyCycle.getName()
val zodiac = sixtyCycle.getEarthBranch().getZodiac().getName()
return "${ganZhi}${zodiac}"
} }