Android Jetpack Compose(可组合)手动触发更改

Android Jetpack Compose (Composable) Trigger Change Manually

我有一些自定义的可组合动画,它使用 LaunchedEffect 在 [minTemperature, maxTemperature] 范围内更改值,我想手动触发动画。这在我更改 minTemperature 和 maxTemperature 值时触发,因此我有 LaunchedEffect(minTemperature, maxTemperature)。但问题是只有当值更改为新值时才会触发可变状态。

因此,如果我调用 setTemperature() 方法,则不会触发动画。所以我所做的是创建新的状态值 'temperatureAnimationSwitch',这是使用视图模型中的 public 方法 startTemperatureAnimation() 手动切换的。因此,这将触发 LaunchedEffect 的重新启动。

我的问题是:

  1. 这是使用开关值的最佳方法吗?
  2. 当 minTemperature 或 maxTemperature 值设置为之前的值时更改事件是否有触发动画的方法?
  3. 有没有类似'state, flow, 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) 
}

我认为你需要设置 SnapshotMutationPolicy of State object to neverEqualPolicy()。这将报告对该对象的所有写入,无论该值是否更改。

    private val _minTemperature = mutableStateOf(-22f, neverEqualPolicy())
    private val _maxTemperature = mutableStateOf(12f, neverEqualPolicy())