Move collapse animation from animateFloatAsState to ViewModel Animatable with spring spec
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
e53c3d8705
commit
35cbcaf430
@ -1,8 +1,11 @@
|
|||||||
package plus.rua.project
|
package plus.rua.project
|
||||||
|
|
||||||
|
import androidx.compose.animation.core.Animatable
|
||||||
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
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.datetime.DatePeriod
|
import kotlinx.datetime.DatePeriod
|
||||||
import kotlinx.datetime.LocalDate
|
import kotlinx.datetime.LocalDate
|
||||||
import kotlinx.datetime.TimeZone
|
import kotlinx.datetime.TimeZone
|
||||||
@ -19,7 +22,7 @@ data class CalendarDay(
|
|||||||
val isSelected: Boolean
|
val isSelected: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
class CalendarViewModel {
|
class CalendarViewModel(private val coroutineScope: CoroutineScope) {
|
||||||
private val today: LocalDate = Clock.System.todayIn(TimeZone.currentSystemDefault())
|
private val today: LocalDate = Clock.System.todayIn(TimeZone.currentSystemDefault())
|
||||||
|
|
||||||
var selectedDate by mutableStateOf(today)
|
var selectedDate by mutableStateOf(today)
|
||||||
@ -28,8 +31,8 @@ class CalendarViewModel {
|
|||||||
var isCollapsed by mutableStateOf(false)
|
var isCollapsed by mutableStateOf(false)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var collapseProgress by mutableStateOf(0f)
|
private val _collapseAnimatable = Animatable(0f)
|
||||||
private set
|
val collapseProgress: Float get() = _collapseAnimatable.value
|
||||||
|
|
||||||
val currentYear: Int get() = selectedDate.year
|
val currentYear: Int get() = selectedDate.year
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@ -40,13 +43,31 @@ class CalendarViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun collapse() {
|
fun collapse() {
|
||||||
isCollapsed = true
|
if (isCollapsed) return
|
||||||
collapseProgress = 1f
|
coroutineScope.launch {
|
||||||
|
_collapseAnimatable.animateTo(
|
||||||
|
targetValue = 1f,
|
||||||
|
animationSpec = androidx.compose.animation.core.spring(
|
||||||
|
dampingRatio = 0.8f,
|
||||||
|
stiffness = 400f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
isCollapsed = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun expand() {
|
fun expand() {
|
||||||
|
if (!isCollapsed) return
|
||||||
isCollapsed = false
|
isCollapsed = false
|
||||||
collapseProgress = 0f
|
coroutineScope.launch {
|
||||||
|
_collapseAnimatable.animateTo(
|
||||||
|
targetValue = 0f,
|
||||||
|
animationSpec = androidx.compose.animation.core.spring(
|
||||||
|
dampingRatio = 0.8f,
|
||||||
|
stiffness = 400f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getIsoWeekNumber(date: LocalDate): Int {
|
fun getIsoWeekNumber(date: LocalDate): Int {
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package plus.rua.project.ui
|
package plus.rua.project.ui
|
||||||
|
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
|
||||||
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.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@ -37,22 +36,19 @@ fun CalendarMonthPage(
|
|||||||
|
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
weeks.forEachIndexed { weekIndex, week ->
|
weeks.forEachIndexed { weekIndex, week ->
|
||||||
val animatedProgress = animateFloatAsState(
|
val progress = collapseProgress
|
||||||
targetValue = collapseProgress,
|
|
||||||
label = "collapse-$weekIndex"
|
|
||||||
).value
|
|
||||||
|
|
||||||
val isAboveSelected = weekIndex < selectedWeekIndex
|
val isAboveSelected = weekIndex < selectedWeekIndex
|
||||||
val isBelowSelected = weekIndex > selectedWeekIndex
|
val isBelowSelected = weekIndex > selectedWeekIndex
|
||||||
|
|
||||||
val offsetY = when {
|
val offsetY = when {
|
||||||
isAboveSelected -> -animatedProgress * 200f
|
isAboveSelected -> -progress * 200f
|
||||||
isBelowSelected -> animatedProgress * 200f
|
isBelowSelected -> progress * 200f
|
||||||
else -> 0f
|
else -> 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
val alpha = when {
|
val alpha = when {
|
||||||
isAboveSelected || isBelowSelected -> 1f - animatedProgress
|
isAboveSelected || isBelowSelected -> 1f - progress
|
||||||
else -> 1f
|
else -> 1f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@ -20,9 +21,10 @@ import plus.rua.project.CalendarViewModel
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CalendarMonthView(
|
fun CalendarMonthView(
|
||||||
viewModel: CalendarViewModel = remember { CalendarViewModel() },
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val viewModel = remember { CalendarViewModel(coroutineScope) }
|
||||||
val today = remember { Clock.System.todayIn(TimeZone.currentSystemDefault()) }
|
val today = remember { Clock.System.todayIn(TimeZone.currentSystemDefault()) }
|
||||||
var currentYear by remember { mutableIntStateOf(viewModel.currentYear) }
|
var currentYear by remember { mutableIntStateOf(viewModel.currentYear) }
|
||||||
var currentMonth by remember { mutableIntStateOf(viewModel.currentMonth) }
|
var currentMonth by remember { mutableIntStateOf(viewModel.currentMonth) }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user