feat: 月视图年月支持日期选择器跳转

- MonthHeader 新增 onYearMonthClick 回调,点击年月文字打开日期选择器
- CalendarMonthView 集成 DatePickerDialog,选择日期后调用 selectDate
- 复用现有 CalendarPager 动画,跨月跳转时自动平滑翻页

同时包含之前的改动:
- 临时隐藏 SplashActivity 入口,改由 MainActivity 作为 LAUNCHER
- benchmark build type 关闭 R8 混淆与资源压缩,保证 profile 可读性
This commit is contained in:
xfy 2026-06-16 14:19:41 +08:00
parent 85bfba241c
commit a731507b3b
4 changed files with 79 additions and 9 deletions

View File

@ -54,9 +54,11 @@ android {
signingConfig = signingConfigs.getByName("debug")
matchingFallbacks += listOf("release")
// isDebuggable=false 使 macrobenchmark 在模拟器上稳定运行,且 Partial 编译模式可用。
// 代价是生成的 baseline-prof.txt / startup-prof.txt 会包含 R8 混淆后的类名;功能上仍然有效。
// 若需要可人工维护的可读 profile请在真机上使用 debuggable build 或引入 Baseline Profile Gradle plugin
// 关闭混淆,保证生成的 baseline-prof.txt / startup-prof.txt 使用原始类名,
// 避免 R8 混淆签名导致 profile 匹配与维护风险
isDebuggable = false
isMinifyEnabled = false
isShrinkResources = false
}
}

View File

@ -9,20 +9,26 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.YaYa">
<!--
SplashActivity 已临时禁用,不再作为应用入口。
如需恢复启动页,将下面的 MAIN/LAUNCHER intent-filter 从 MainActivity
移回 SplashActivity 即可。
-->
<activity
android:name=".SplashActivity"
android:exported="true"
android:theme="@style/Theme.YaYa.Splash">
android:theme="@style/Theme.YaYa.Splash" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="true" />
<activity
android:name=".AboutActivity"
android:exported="false" />

View File

@ -1,3 +1,5 @@
@file:OptIn(ExperimentalMaterial3Api::class)
package plus.rua.project.ui
import androidx.compose.animation.AnimatedContent
@ -42,11 +44,16 @@ import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
@ -74,9 +81,12 @@ import kotlinx.coroutines.launch
import kotlinx.datetime.LocalDate
import kotlinx.datetime.Month
import kotlinx.datetime.TimeZone
import kotlinx.datetime.atStartOfDayIn
import kotlinx.datetime.number
import kotlinx.datetime.plus
import kotlinx.datetime.toLocalDateTime
import kotlinx.datetime.todayIn
import kotlin.time.Instant
import plus.rua.project.CalendarViewModel
import plus.rua.project.ShiftKind
import plus.rua.project.composeTraceBeginSection
@ -125,6 +135,7 @@ fun CalendarMonthView(
var rowHeightPx by remember { mutableIntStateOf(0) }
var screenWidthPx by remember { mutableIntStateOf(0) }
var isMenuExpanded by remember { mutableStateOf(false) }
var showDatePicker by remember { mutableStateOf(false) }
// 视图切换时自动关闭菜单
LaunchedEffect(isYearView) {
@ -214,7 +225,8 @@ fun CalendarMonthView(
month = currentMonth,
weekNumber = weekNumber,
showToday = selectedDate != today,
onToday = onToday
onToday = onToday,
onYearMonthClick = { showDatePicker = true }
)
WeekdayHeader(
modifier = Modifier.fillMaxWidth().padding(bottom = ROW_PADDING_DP.dp)
@ -439,6 +451,34 @@ fun CalendarMonthView(
}
}
}
if (showDatePicker) {
val datePickerState = rememberDatePickerState(
initialSelectedDateMillis = selectedDate.toEpochMillis()
)
DatePickerDialog(
onDismissRequest = { showDatePicker = false },
confirmButton = {
TextButton(
onClick = {
datePickerState.selectedDateMillis?.let { millis ->
viewModel.selectDate(millis.toLocalDate())
}
showDatePicker = false
}
) {
Text("确定")
}
},
dismissButton = {
TextButton(onClick = { showDatePicker = false }) {
Text("取消")
}
}
) {
DatePicker(state = datePickerState)
}
}
}
}
@ -611,3 +651,19 @@ private fun MenuItem(
)
}
}
/**
* [LocalDate] 转换为 UTC 午夜的 epoch 毫秒
*
* 用于 DatePicker 初始选中值 [Long.toLocalDate] 成对使用
*/
private fun LocalDate.toEpochMillis(): Long =
this.atStartOfDayIn(TimeZone.UTC).toEpochMilliseconds()
/**
* epoch 毫秒转换为 UTC 日期的 [LocalDate]
*
* DatePicker 返回选中日期的 UTC 午夜毫秒经此函数得到本地逻辑日期
*/
private fun Long.toLocalDate(): LocalDate =
Instant.fromEpochMilliseconds(this).toLocalDateTime(TimeZone.UTC).date

View File

@ -34,6 +34,7 @@ import androidx.compose.ui.unit.sp
* @param weekNumber 当前 ISO 周号
* @param showToday 是否显示今天按钮 selectedDate today
* @param onToday 点击今天按钮跳转今天
* @param onYearMonthClick 点击"年月"文字打开日期选择器
* @param modifier 外部布局修饰符
*/
@Composable
@ -43,6 +44,7 @@ fun MonthHeader(
weekNumber: Int,
showToday: Boolean,
onToday: (() -> Unit)? = null,
onYearMonthClick: () -> Unit = {},
modifier: Modifier = Modifier
) {
Row(
@ -66,7 +68,11 @@ fun MonthHeader(
Text(
text = "${y}${m}",
color = MaterialTheme.colorScheme.onBackground,
style = MaterialTheme.typography.titleLarge
style = MaterialTheme.typography.titleLarge,
modifier = Modifier
.clip(RoundedCornerShape(8.dp))
.clickable(onClick = onYearMonthClick)
.padding(horizontal = 4.dp, vertical = 2.dp)
)
}
Spacer(modifier = Modifier.width(6.dp))