Wire year view into CalendarMonthView, MonthHeader and ViewModel
- CalendarViewModel: year view state and animation methods - CalendarMonthView: graphicsLayer zoom overlay, BottomCard hiding - MonthHeader: toggle year view on click, "今天" button
This commit is contained in:
parent
995693cb5d
commit
731a1bb6a1
@ -1,7 +1,9 @@
|
|||||||
package plus.rua.project
|
package plus.rua.project
|
||||||
|
|
||||||
import androidx.compose.animation.core.Animatable
|
import androidx.compose.animation.core.Animatable
|
||||||
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
import androidx.compose.animation.core.spring
|
import androidx.compose.animation.core.spring
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@ -61,6 +63,16 @@ class CalendarViewModel(
|
|||||||
|
|
||||||
val currentYear: Int get() = selectedDate.year
|
val currentYear: Int get() = selectedDate.year
|
||||||
|
|
||||||
|
var isYearView by mutableStateOf(false)
|
||||||
|
private set
|
||||||
|
|
||||||
|
private val _yearViewAnimatable = Animatable(0f)
|
||||||
|
val yearViewProgress: Float get() = _yearViewAnimatable.value
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||||
|
var yearViewYear by mutableStateOf(today.year)
|
||||||
|
private set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 选中指定日期。
|
* 选中指定日期。
|
||||||
*
|
*
|
||||||
@ -70,6 +82,51 @@ class CalendarViewModel(
|
|||||||
selectedDate = date
|
selectedDate = date
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换年视图。仅在展开态可用。
|
||||||
|
*/
|
||||||
|
fun toggleYearView() {
|
||||||
|
if (isCollapsed) return
|
||||||
|
coroutineScope.launch {
|
||||||
|
if (isYearView) {
|
||||||
|
_yearViewAnimatable.animateTo(
|
||||||
|
0f, tween(400, easing = FastOutSlowInEasing)
|
||||||
|
)
|
||||||
|
isYearView = false
|
||||||
|
} else {
|
||||||
|
isYearView = true
|
||||||
|
_yearViewAnimatable.snapTo(0f)
|
||||||
|
_yearViewAnimatable.animateTo(
|
||||||
|
1f, tween(400, easing = FastOutSlowInEasing)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从年视图选择月份后返回月视图。
|
||||||
|
*/
|
||||||
|
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||||
|
fun selectMonthFromYearView(month: Int) {
|
||||||
|
val date = if (yearViewYear == today.year && today.month.number == month) today
|
||||||
|
else LocalDate(yearViewYear, month, 1)
|
||||||
|
selectedDate = date
|
||||||
|
coroutineScope.launch {
|
||||||
|
_yearViewAnimatable.animateTo(
|
||||||
|
0f, tween(400, easing = FastOutSlowInEasing)
|
||||||
|
)
|
||||||
|
isYearView = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun incrementYear() {
|
||||||
|
yearViewYear++
|
||||||
|
}
|
||||||
|
|
||||||
|
fun decrementYear() {
|
||||||
|
yearViewYear--
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 展开状态下拖拽折叠,delta 正值推动 progress 向 1(折叠方向)。
|
* 展开状态下拖拽折叠,delta 正值推动 progress 向 1(折叠方向)。
|
||||||
*
|
*
|
||||||
|
|||||||
@ -19,6 +19,8 @@ import androidx.compose.runtime.setValue
|
|||||||
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.clipToBounds
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
|
import androidx.compose.ui.graphics.TransformOrigin
|
||||||
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.layout.onSizeChanged
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@ -34,10 +36,10 @@ import kotlin.math.abs
|
|||||||
import kotlin.time.Clock
|
import kotlin.time.Clock
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日历主界面,包含月/周视图切换和折叠动画。
|
* 日历主界面,包含月/周视图切换、折叠动画和年视图缩放转场。
|
||||||
*
|
*
|
||||||
* 折叠时日历从月视图收缩为周视图(1行),BottomCard 同步上移填充空间。
|
* 折叠时日历从月视图收缩为周视图(1行),BottomCard 同步上移填充空间。
|
||||||
* 支持动态行数(4/5/6行),滑动切换月份时 BottomCard 跟手移动。
|
* 点击月份标题切换年视图,以当前月为锚点缩放转场。
|
||||||
*
|
*
|
||||||
* @param modifier 外部布局修饰符
|
* @param modifier 外部布局修饰符
|
||||||
*/
|
*/
|
||||||
@ -59,11 +61,11 @@ fun CalendarMonthView(
|
|||||||
var rowHeightPx by remember { mutableIntStateOf(0) }
|
var rowHeightPx by remember { mutableIntStateOf(0) }
|
||||||
var screenWidthPx by remember { mutableIntStateOf(0) }
|
var screenWidthPx by remember { mutableIntStateOf(0) }
|
||||||
var screenHeightPx by remember { mutableIntStateOf(0) }
|
var screenHeightPx by remember { mutableIntStateOf(0) }
|
||||||
|
var calendarContentHeightPx by remember { mutableIntStateOf(0) }
|
||||||
|
|
||||||
val pagerState = rememberPagerState(initialPage = START_PAGE, pageCount = { Int.MAX_VALUE })
|
val pagerState = rememberPagerState(initialPage = START_PAGE, pageCount = { Int.MAX_VALUE })
|
||||||
|
|
||||||
// 折叠态 WeekPager 切月时,持续同步 CalendarPager 的 pagerState,
|
// 折叠态 WeekPager 切月时,持续同步 CalendarPager 的 pagerState
|
||||||
// 避免展开时 CalendarPager 首帧显示旧月份导致闪白
|
|
||||||
LaunchedEffect(viewModel.selectedDate) {
|
LaunchedEffect(viewModel.selectedDate) {
|
||||||
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||||
val targetPage = yearMonthToPage(
|
val targetPage = yearMonthToPage(
|
||||||
@ -76,6 +78,7 @@ fun CalendarMonthView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val collapseProgress = viewModel.collapseProgress
|
val collapseProgress = viewModel.collapseProgress
|
||||||
|
val yearProgress = viewModel.yearViewProgress
|
||||||
val headerHeightPx = monthHeaderHeightPx + weekdayHeaderHeightPx
|
val headerHeightPx = monthHeaderHeightPx + weekdayHeaderHeightPx
|
||||||
val rowPaddingPx = with(density) { ROW_PADDING_DP.dp.toPx() }.toInt()
|
val rowPaddingPx = with(density) { ROW_PADDING_DP.dp.toPx() }.toInt()
|
||||||
val cardGapPx = with(density) {
|
val cardGapPx = with(density) {
|
||||||
@ -86,8 +89,6 @@ fun CalendarMonthView(
|
|||||||
).dp.toPx()
|
).dp.toPx()
|
||||||
}.toInt()
|
}.toInt()
|
||||||
|
|
||||||
// 翻页时在相邻月份行数之间插值,使 BottomCard 高度平滑过渡
|
|
||||||
// abs(fraction) > 阈值时启用插值,避免静止时的浮点抖动
|
|
||||||
val interpolatedWeeks by remember {
|
val interpolatedWeeks by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
val fraction = pagerState.currentPageOffsetFraction
|
val fraction = pagerState.currentPageOffsetFraction
|
||||||
@ -103,9 +104,6 @@ fun CalendarMonthView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预估行高:DayCell aspectRatio=1,宽度 = (screenWidth - horizontalPadding) / 7
|
|
||||||
// 加上 Row 的 vertical padding (6dp × 2)
|
|
||||||
// 用于 rowHeightPx 尚未测量时的 fallback,避免首次布局高度为 0
|
|
||||||
val estimatedRowHeightPx = if (screenWidthPx > 0) {
|
val estimatedRowHeightPx = if (screenWidthPx > 0) {
|
||||||
val cellWidth =
|
val cellWidth =
|
||||||
(screenWidthPx - with(density) { (HORIZONTAL_PADDING_DP * 2).dp.toPx() }) / 7
|
(screenWidthPx - with(density) { (HORIZONTAL_PADDING_DP * 2).dp.toPx() }) / 7
|
||||||
@ -114,14 +112,8 @@ fun CalendarMonthView(
|
|||||||
} else 0
|
} else 0
|
||||||
|
|
||||||
val effectiveRowHeightPx = if (rowHeightPx > 0) rowHeightPx else estimatedRowHeightPx
|
val effectiveRowHeightPx = if (rowHeightPx > 0) rowHeightPx else estimatedRowHeightPx
|
||||||
|
|
||||||
val effectiveWeeks = interpolatedWeeks
|
val effectiveWeeks = interpolatedWeeks
|
||||||
|
|
||||||
// 折叠时网格高度公式(与 CalendarMonthPage 一致):
|
|
||||||
// collapseProgress=0 展开时 gridH = rowH × weeks;collapseProgress=1 折叠时 gridH = rowH × 1
|
|
||||||
// 中间态:gridH = rowH × (1 + (weeks-1) × (1-collapseProgress))
|
|
||||||
// 直接计算而非 derivedStateOf:effectiveRowHeightPx 依赖 rowHeightPx state,
|
|
||||||
// derivedStateOf 无法追踪非 State 局部变量,rowHeightPx 从 0 变为测量值时 gridHeightPx 不会更新
|
|
||||||
val gridHeightPx = if (effectiveRowHeightPx > 0) {
|
val gridHeightPx = if (effectiveRowHeightPx > 0) {
|
||||||
val rowH = effectiveRowHeightPx.toFloat()
|
val rowH = effectiveRowHeightPx.toFloat()
|
||||||
if (collapseProgress > OFFSET_FRACTION_THRESHOLD) {
|
if (collapseProgress > OFFSET_FRACTION_THRESHOLD) {
|
||||||
@ -131,12 +123,10 @@ fun CalendarMonthView(
|
|||||||
}
|
}
|
||||||
} else 0
|
} else 0
|
||||||
|
|
||||||
// BottomCard 高度 = 屏幕剩余空间(屏幕高度 - 日历区域高度)
|
|
||||||
val calendarAreaHeightPx = headerHeightPx + gridHeightPx + rowPaddingPx + cardGapPx
|
val calendarAreaHeightPx = headerHeightPx + gridHeightPx + rowPaddingPx + cardGapPx
|
||||||
val cardHeightPx =
|
val cardHeightPx =
|
||||||
if (screenHeightPx > 0 && calendarAreaHeightPx > 0) screenHeightPx - calendarAreaHeightPx else 0
|
if (screenHeightPx > 0 && calendarAreaHeightPx > 0) screenHeightPx - calendarAreaHeightPx else 0
|
||||||
|
|
||||||
// 行高已知时约束 pager 高度防止内容溢出;否则让 pager 自由扩展以触发首次行高测量
|
|
||||||
val pagerModifier = if (rowHeightPx > 0 && gridHeightPx > 0) {
|
val pagerModifier = if (rowHeightPx > 0 && gridHeightPx > 0) {
|
||||||
Modifier
|
Modifier
|
||||||
.height(with(density) { gridHeightPx.toDp() })
|
.height(with(density) { gridHeightPx.toDp() })
|
||||||
@ -145,6 +135,18 @@ fun CalendarMonthView(
|
|||||||
Modifier
|
Modifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 年视图锚点缩放:当前月在 4×3 网格中的归一化位置
|
||||||
|
val anchorPivotX = ((currentMonth - 1) % 3 + 0.5f) / 3f
|
||||||
|
val anchorPivotY = ((currentMonth - 1) / 3 + 0.5f) / 4f
|
||||||
|
|
||||||
|
// 月视图层缩放:从 1f 缩小到 ~0.3f(年网格单格 vs 月视图大小比)
|
||||||
|
val monthScale = 1f - yearProgress * 0.7f
|
||||||
|
val monthAlpha = (1f - yearProgress * 1.4f).coerceIn(0f, 1f)
|
||||||
|
|
||||||
|
// 年视图层缩放:从 ~3.3f 放大到 1f
|
||||||
|
val yearScale = lerp(3.3f, 1f, yearProgress)
|
||||||
|
val yearAlpha = ((yearProgress - 0.2f) / 0.8f).coerceIn(0f, 1f)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@ -154,12 +156,25 @@ fun CalendarMonthView(
|
|||||||
screenHeightPx = size.height
|
screenHeightPx = size.height
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.padding(horizontal = HORIZONTAL_PADDING_DP.dp)) {
|
// 月视图层
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.graphicsLayer {
|
||||||
|
scaleX = monthScale
|
||||||
|
scaleY = monthScale
|
||||||
|
alpha = monthAlpha
|
||||||
|
transformOrigin = TransformOrigin(anchorPivotX, anchorPivotY)
|
||||||
|
}
|
||||||
|
.padding(horizontal = HORIZONTAL_PADDING_DP.dp)
|
||||||
|
) {
|
||||||
MonthHeader(
|
MonthHeader(
|
||||||
year = currentYear,
|
year = currentYear,
|
||||||
month = currentMonth,
|
month = currentMonth,
|
||||||
weekNumber = viewModel.getIsoWeekNumber(viewModel.selectedDate),
|
weekNumber = viewModel.getIsoWeekNumber(viewModel.selectedDate),
|
||||||
onClick = {
|
showToday = viewModel.selectedDate != today,
|
||||||
|
onToggleYearView = { viewModel.toggleYearView() },
|
||||||
|
onToday = {
|
||||||
viewModel.selectDate(today)
|
viewModel.selectDate(today)
|
||||||
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||||
val targetPage = yearMonthToPage(
|
val targetPage = yearMonthToPage(
|
||||||
@ -180,8 +195,6 @@ fun CalendarMonthView(
|
|||||||
weekdayHeaderHeightPx = size.height
|
weekdayHeaderHeightPx = size.height
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// 完全折叠且无动画时切换到 WeekPager(单行高效渲染),
|
|
||||||
// 否则使用 CalendarPager(含折叠动画和下拉恢复过程)
|
|
||||||
if (viewModel.isCollapsed && viewModel.collapseProgress >= 1f) {
|
if (viewModel.isCollapsed && viewModel.collapseProgress >= 1f) {
|
||||||
WeekPager(
|
WeekPager(
|
||||||
selectedDate = viewModel.selectedDate,
|
selectedDate = viewModel.selectedDate,
|
||||||
@ -193,11 +206,9 @@ fun CalendarMonthView(
|
|||||||
today in weekMonday..weekSunday -> today
|
today in weekMonday..weekSunday -> today
|
||||||
weekMonday.month != weekSunday.month -> {
|
weekMonday.month != weekSunday.month -> {
|
||||||
if (weekMonday < viewModel.selectedDate) {
|
if (weekMonday < viewModel.selectedDate) {
|
||||||
// 后退到跨月周(如从5月回到4月27-5月3):选较晚月份1号,留在当月
|
|
||||||
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||||
LocalDate(weekSunday.year, weekSunday.month.number, 1)
|
LocalDate(weekSunday.year, weekSunday.month.number, 1)
|
||||||
} else {
|
} else {
|
||||||
// 前进到跨月周(如从4月前进到4月27-5月3):选该周周一,留在上个月
|
|
||||||
weekMonday
|
weekMonday
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,8 +224,7 @@ fun CalendarMonthView(
|
|||||||
today = today,
|
today = today,
|
||||||
onDateClick = { date -> viewModel.selectDate(date) },
|
onDateClick = { date -> viewModel.selectDate(date) },
|
||||||
onMonthChanged = { year, month ->
|
onMonthChanged = { year, month ->
|
||||||
// 优先选中当月内的今天,否则选中该月1号
|
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||||
@Suppress("DEPRECATION") // monthNumber 无替代 API,kotlinx-datetime 尚未提供新接口
|
|
||||||
val date = if (year == today.year && today.month.number == month) today
|
val date = if (year == today.year && today.month.number == month) today
|
||||||
else LocalDate(year, month, 1)
|
else LocalDate(year, month, 1)
|
||||||
viewModel.selectDate(date)
|
viewModel.selectDate(date)
|
||||||
@ -231,23 +241,58 @@ fun CalendarMonthView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拖拽范围 = 折叠时日历实际高度变化量 (weeks-1)×rowHeight,使手指移动与视觉变化 1:1 对应
|
// 年视图层
|
||||||
val dragRangeMinPx = with(density) { DRAG_RANGE_MIN_DP.dp.toPx() }
|
if (viewModel.isYearView || yearProgress > 0.01f) {
|
||||||
val dragRangePx = if (effectiveRowHeightPx > 0) {
|
YearGridView(
|
||||||
maxOf((effectiveWeeks - 1) * effectiveRowHeightPx.toFloat(), dragRangeMinPx)
|
year = viewModel.yearViewYear,
|
||||||
} else {
|
selectedMonth = if (viewModel.yearViewYear == currentYear) currentMonth else 0,
|
||||||
dragRangeMinPx
|
onMonthClick = { month ->
|
||||||
|
viewModel.selectMonthFromYearView(month)
|
||||||
|
// 同步 CalendarPager 到目标月份
|
||||||
|
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||||
|
val targetPage = yearMonthToPage(
|
||||||
|
viewModel.yearViewYear, month,
|
||||||
|
today.year, today.month.number
|
||||||
|
)
|
||||||
|
if (targetPage != pagerState.currentPage) {
|
||||||
|
coroutineScope.launch { pagerState.scrollToPage(targetPage) }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onYearChange = { newYear ->
|
||||||
|
if (newYear > viewModel.yearViewYear) viewModel.incrementYear()
|
||||||
|
else viewModel.decrementYear()
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.graphicsLayer {
|
||||||
|
scaleX = yearScale
|
||||||
|
scaleY = yearScale
|
||||||
|
alpha = yearAlpha
|
||||||
|
transformOrigin = TransformOrigin(anchorPivotX, anchorPivotY)
|
||||||
|
}
|
||||||
|
.padding(horizontal = HORIZONTAL_PADDING_DP.dp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cardHeightPx > 0) {
|
// BottomCard:年视图时隐藏
|
||||||
BottomCard(
|
if (yearProgress < 0.01f) {
|
||||||
viewModel = viewModel,
|
val dragRangeMinPx = with(density) { DRAG_RANGE_MIN_DP.dp.toPx() }
|
||||||
dragRangePx = dragRangePx,
|
val dragRangePx = if (effectiveRowHeightPx > 0) {
|
||||||
modifier = Modifier
|
maxOf((effectiveWeeks - 1) * effectiveRowHeightPx.toFloat(), dragRangeMinPx)
|
||||||
.fillMaxWidth()
|
} else {
|
||||||
.height(with(density) { cardHeightPx.toDp() })
|
dragRangeMinPx
|
||||||
.align(Alignment.BottomCenter)
|
}
|
||||||
)
|
|
||||||
|
if (cardHeightPx > 0) {
|
||||||
|
BottomCard(
|
||||||
|
viewModel = viewModel,
|
||||||
|
dragRangePx = dragRangePx,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(with(density) { cardHeightPx.toDp() })
|
||||||
|
.align(Alignment.BottomCenter)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,12 +13,15 @@ import androidx.compose.foundation.layout.Spacer
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
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.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.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 月份标题栏,显示"年月"文字和 ISO 周号。
|
* 月份标题栏,显示"年月"文字和 ISO 周号。
|
||||||
@ -26,6 +29,9 @@ import androidx.compose.ui.unit.dp
|
|||||||
* @param year 年份
|
* @param year 年份
|
||||||
* @param month 月份(1-12)
|
* @param month 月份(1-12)
|
||||||
* @param weekNumber 当前 ISO 周号
|
* @param weekNumber 当前 ISO 周号
|
||||||
|
* @param showToday 是否显示「今天」按钮(当 selectedDate ≠ today 时)
|
||||||
|
* @param onToggleYearView 点击标题切换年视图
|
||||||
|
* @param onToday 点击「今天」按钮跳转今天
|
||||||
* @param modifier 外部布局修饰符
|
* @param modifier 外部布局修饰符
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
@ -33,14 +39,16 @@ fun MonthHeader(
|
|||||||
year: Int,
|
year: Int,
|
||||||
month: Int,
|
month: Int,
|
||||||
weekNumber: Int,
|
weekNumber: Int,
|
||||||
onClick: (() -> Unit)? = null,
|
showToday: Boolean,
|
||||||
|
onToggleYearView: () -> Unit,
|
||||||
|
onToday: (() -> Unit)? = null,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 14.dp, horizontal = 12.dp)
|
.padding(vertical = 14.dp, horizontal = 12.dp)
|
||||||
.then(if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier),
|
.clickable(onClick = onToggleYearView),
|
||||||
verticalAlignment = Alignment.Bottom
|
verticalAlignment = Alignment.Bottom
|
||||||
) {
|
) {
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
@ -79,5 +87,17 @@ fun MonthHeader(
|
|||||||
style = MaterialTheme.typography.bodySmall
|
style = MaterialTheme.typography.bodySmall
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
if (showToday && onToday != null) {
|
||||||
|
Text(
|
||||||
|
text = "今天",
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(12.dp))
|
||||||
|
.clickable(onClick = onToday)
|
||||||
|
.padding(horizontal = 10.dp, vertical = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user