Revert "feat: 添加年月滚轮选择器,支持触觉反馈"

This reverts commit bbe51051ae83d56fda8ad965f7b73a014ddea7b8.
This commit is contained in:
meyou 2026-05-26 07:33:15 +08:00
parent 0b6d9ea87a
commit dfb820d610
No known key found for this signature in database
5 changed files with 3 additions and 304 deletions

View File

@ -207,21 +207,12 @@ fun CalendarMonthView(
val onToday = remember(viewModel, today) {
{ viewModel.selectDate(today) }
}
val onMonthYearSelect = remember(viewModel, today) {
{ year: Int, month: Int ->
@Suppress("DEPRECATION")
val date = if (year == today.year && today.month.number == month) today
else LocalDate(year, month, 1)
viewModel.selectDate(date)
}
}
MonthHeader(
year = currentYear,
month = currentMonth,
weekNumber = weekNumber,
showToday = selectedDate != today,
onToday = onToday,
onMonthYearSelect = onMonthYearSelect
onToday = onToday
)
WeekdayHeader(
modifier = Modifier.fillMaxWidth().padding(bottom = ROW_PADDING_DP.dp)

View File

@ -19,9 +19,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@ -32,14 +29,11 @@ import androidx.compose.ui.unit.sp
/**
* 月份标题栏显示"年月"文字和 ISO 周号
*
* 点击年月文字弹出滚轮选择器可快速跳转到任意年月
*
* @param year 年份
* @param month 月份1-12
* @param weekNumber 当前 ISO 周号
* @param showToday 是否显示今天按钮 selectedDate today
* @param onToday 点击今天按钮跳转今天
* @param onMonthYearSelect 年月选择回调
* @param modifier 外部布局修饰符
*/
@Composable
@ -49,23 +43,8 @@ fun MonthHeader(
weekNumber: Int,
showToday: Boolean,
onToday: (() -> Unit)? = null,
onMonthYearSelect: ((year: Int, month: Int) -> Unit)? = null,
modifier: Modifier = Modifier
) {
var showPicker by remember { mutableStateOf(false) }
if (showPicker && onMonthYearSelect != null) {
MonthYearPickerDialog(
currentYear = year,
currentMonth = month,
onConfirm = { y, m ->
onMonthYearSelect(y, m)
showPicker = false
},
onDismiss = { showPicker = false }
)
}
Row(
modifier = modifier
.fillMaxWidth()
@ -87,13 +66,7 @@ fun MonthHeader(
Text(
text = "${y}${m}",
color = MaterialTheme.colorScheme.onBackground,
style = MaterialTheme.typography.titleLarge,
modifier = if (onMonthYearSelect != null) {
Modifier
.clip(RoundedCornerShape(8.dp))
.clickable { showPicker = true }
.padding(horizontal = 4.dp, vertical = 2.dp)
} else Modifier
style = MaterialTheme.typography.titleLarge
)
}
Spacer(modifier = Modifier.width(6.dp))

View File

@ -1,122 +0,0 @@
package plus.rua.project.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
private val Years = (1970..2100).map { "${it}" }
private val Months = (1..12).map { "${it}" }
/**
* 年月滚轮选择器弹窗
*
* 左侧年份滚轮 + 右侧月份滚轮每次滚动触发触觉反馈
*
* @param currentYear 当前年份
* @param currentMonth 当前月份1-12
* @param onConfirm 确认回调参数为 (year, month)
* @param onDismiss 关闭回调
*/
@Composable
fun MonthYearPickerDialog(
currentYear: Int,
currentMonth: Int,
onConfirm: (year: Int, month: Int) -> Unit,
onDismiss: () -> Unit
) {
var selectedYear by remember { mutableIntStateOf(currentYear) }
var selectedMonth by remember { mutableIntStateOf(currentMonth) }
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text("选择年月", style = MaterialTheme.typography.titleMedium)
},
text = {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
WheelPicker(
items = Years,
selectedIndex = selectedYear - 1970,
onSelectedChange = { selectedYear = it + 1970 },
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(16.dp))
WheelPicker(
items = Months,
selectedIndex = selectedMonth - 1,
onSelectedChange = { selectedMonth = it + 1 },
modifier = Modifier.weight(1f)
)
}
},
confirmButton = {
TextButton(onClick = { onConfirm(selectedYear, selectedMonth) }) {
Text("确定")
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text("取消")
}
}
)
}
/**
* 年份滚轮选择器弹窗用于年视图
*
* @param currentYear 当前年份
* @param onConfirm 确认回调参数为 year
* @param onDismiss 关闭回调
*/
@Composable
fun YearPickerDialog(
currentYear: Int,
onConfirm: (year: Int) -> Unit,
onDismiss: () -> Unit
) {
var selectedYear by remember { mutableIntStateOf(currentYear) }
AlertDialog(
onDismissRequest = onDismiss,
title = {
Text("选择年份", style = MaterialTheme.typography.titleMedium)
},
text = {
WheelPicker(
items = Years,
selectedIndex = selectedYear - 1970,
onSelectedChange = { selectedYear = it + 1970 },
modifier = Modifier.fillMaxWidth()
)
},
confirmButton = {
TextButton(onClick = { onConfirm(selectedYear) }) {
Text("确定")
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text("取消")
}
}
)
}

View File

@ -1,126 +0,0 @@
package plus.rua.project.ui
import android.view.HapticFeedbackConstants
import android.view.View
import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlin.math.abs
private val ItemHeight = 48.dp
private const val VisibleItemCount = 5
private val WheelHeight = ItemHeight * VisibleItemCount
private const val PaddingItems = VisibleItemCount / 2
/**
* 通用滚轮选择器支持惯性吸附和触觉反馈
*
* 滚动停止后才触发选中变更和触觉反馈避免快速滑动时抖动
*
* @param items 显示的项目列表
* @param selectedIndex 当前选中项索引
* @param onSelectedChange 选中项变化回调仅在滚动停止后触发
* @param modifier 外部布局修饰符
*/
@Composable
fun WheelPicker(
items: List<String>,
selectedIndex: Int,
onSelectedChange: (Int) -> Unit,
modifier: Modifier = Modifier,
) {
val listState = rememberLazyListState(
initialFirstVisibleItemIndex = (selectedIndex - PaddingItems).coerceAtLeast(0)
)
val view = LocalView.current
// 视觉中心项(实时,仅用于渲染高亮)
val visualCenter by remember {
derivedStateOf {
val viewportCenter = listState.layoutInfo.viewportSize.height / 2f
listState.layoutInfo.visibleItemsInfo.minByOrNull {
abs(it.offset + it.size / 2f - viewportCenter)
}?.index?.let { it - PaddingItems } ?: selectedIndex
}
}
// 初始滚动到选中项
LaunchedEffect(selectedIndex) {
val target = (selectedIndex - PaddingItems).coerceAtLeast(0)
if (listState.firstVisibleItemIndex != target) {
listState.scrollToItem(target)
}
}
// 滚动停止后:计算最终中心项 → 触发选中变更 + 触觉反馈
LaunchedEffect(listState) {
var lastSettled = selectedIndex
snapshotFlow { listState.isScrollInProgress to listState.layoutInfo}
.collect { (scrolling, _) ->
if (!scrolling) {
val center = visualCenter.coerceIn(0, items.lastIndex)
if (center != lastSettled) {
lastSettled = center
onSelectedChange(center)
view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)
}
}
}
}
val snapLayoutInfoProvider = remember(listState) {
SnapLayoutInfoProvider(listState)
}
LazyColumn(
state = listState,
modifier = modifier.height(WheelHeight),
flingBehavior = rememberSnapFlingBehavior(snapLayoutInfoProvider),
horizontalAlignment = Alignment.CenterHorizontally,
userScrollEnabled = true
) {
items(items.size + PaddingItems * 2) { layoutIndex ->
val centerIndex = layoutIndex - PaddingItems
val isValid = centerIndex in items.indices
Box(
modifier = Modifier
.height(ItemHeight)
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
if (isValid) {
val isSelected = centerIndex == visualCenter
Text(
text = items[centerIndex],
color = if (isSelected) MaterialTheme.colorScheme.onSurface
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f),
fontSize = if (isSelected) 20.sp else 16.sp,
fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal,
style = LocalTextStyle.current
)
}
}
}
}
}

View File

@ -351,19 +351,6 @@ fun YearHeader(
onYearChange: (Int) -> Unit,
modifier: Modifier = Modifier
) {
var showPicker by remember { mutableStateOf(false) }
if (showPicker) {
YearPickerDialog(
currentYear = year,
onConfirm = { y ->
onYearChange(y)
showPicker = false
},
onDismiss = { showPicker = false }
)
}
Column(
modifier = modifier
.fillMaxWidth()
@ -386,11 +373,7 @@ fun YearHeader(
text = "${y}",
color = MaterialTheme.colorScheme.onBackground,
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
modifier = Modifier
.clip(RoundedCornerShape(8.dp))
.clickable { showPicker = true }
.padding(horizontal = 4.dp, vertical = 2.dp)
fontWeight = FontWeight.Bold
)
}
Spacer(modifier = Modifier.weight(1f))