Android Jetpack Compose (Composable) запускает изменение вручную
У меня есть некоторая пользовательская составная анимация, которая изменяет значение в диапазоне [minTemperature, maxTemperature] с помощью LaunchedEffect, и я хочу запустить анимацию вручную. Это срабатывает, когда я изменяю значения minTemperature и maxTemperature, поэтому у меня есть LaunchedEffect(minTemperature, maxTemperature). Но проблема в том, что изменяемое состояние запускается ТОЛЬКО КОГДА ЗНАЧЕНИЕ ИЗМЕНЯЕТСЯ НА НОВОЕ ЗНАЧЕНИЕ.
Поэтому, если я вызову метод setTemperature(), анимация не запустится. Итак, что я сделал, так это создал новое значение состояния «temperatureAnimationSwitch», которое переключается вручную с помощью общедоступного метода startTemperatureAnimation() из модели представления. Так что это вызовет перезапуск LaunchedEffect.
Мои вопросы:
- Это лучший подход с использованием значения переключателя?
- Есть ли способ запустить анимацию, когда значения minTemperature или maxTemperature изменяются, когда установлено их предыдущее значение?
- Есть ли объект, похожий на «состояние, поток, livedata..», но он может запускаться, даже когда мы меняем его текущее значение на себя.
@HiltViewModel
class CityWeatherViewModel @Inject constructor(
private val getCityWeather: GetCityWeather
) : ViewModel() {
//region Temperature Component
private val _temperatureAnimationSwitch = mutableStateOf(true)
val temperatureAnimationSwitch: State<Boolean> = _temperatureAnimationSwitch
private val _minTemperature = mutableStateOf(-22f)
val minTemperature: State<Float> = _minTemperature
private val _maxTemperature = mutableStateOf(12f)
val maxTemperature: State<Float> = _maxTemperature
fun startTemperatureAnimation() {
_temperatureAnimationSwitch.value = !_temperatureAnimationSwitch.value
}
fun setTemperature(minTemperature: Float = _minTemperature.value, maxTemperature: Float = _maxTemperature.value) {
_minTemperature.value = minTemperature
_maxTemperature.value = maxTemperature
}
//endregion
}
@Composable
fun TemperatureCanvas(
viewModel: CityWeatherViewModel,
minTemperature: Float = viewModel.minTemperature.value,
maxTemperature: Float = viewModel.maxTemperature.value,
temperatureAnimationSwitch: Boolean = viewModel.temperatureAnimationSwitch.value
) {
var temperatureForText by remember { mutableStateOf(0) }
LaunchedEffect(temperatureAnimationSwitch) {
val animation = TargetBasedAnimation(
animationSpec = tween(1500),
typeConverter = Int.VectorConverter,
initialValue = minTemperature,
targetValue = maxTemperature
)
val startTime = withFrameNanos { it }
do {
val playTime = withFrameNanos { it } - startTime
temperatureForText = animation.getValueFromNanos(playTime)
} while (temperatureForText < maxTemperature)
}
// the text will be update with the animated value 'temperatureForText'
Text(text = temperatureForText)
}
1 ответ
Я думаю, вам нужно установитьSnapshotMutationPolicy
государства возражают противneverEqualPolicy()
. Это сообщит обо всех операциях записи в этот объект, независимо от того, изменилось значение или нет.
private val _minTemperature = mutableStateOf(-22f, neverEqualPolicy())
private val _maxTemperature = mutableStateOf(12f, neverEqualPolicy())