You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Kotlin StateFlow前一个值以判断导航动画方向

实现方案

你需要的rememberHistory能力可以通过自定义Flow扩展操作符实现,核心逻辑是在流内部存储上一次发射的值,每次新值到来时将「当前值+上一次值」配对发射。

1. 自定义Flow扩展函数

fun <T> Flow<T>.rememberHistory(skipFirstNullHistory: Boolean = false): Flow<Pair<T, T?>> = flow {
    var lastValue: T? = null
    collect { currentValue ->
        if (!skipFirstNullHistory || lastValue != null) {
            emit(currentValue to lastValue)
        }
        lastValue = currentValue
    }
}

参数skipFirstNullHistory用来控制是否跳过首次发射时历史值为null的情况,适合首次进入首页不需要动画的场景。

2. 调整导航逻辑实现动画判断

viewModel.destinations
    .rememberHistory(skipFirstNullHistory = true)
    .collect { (current, last) ->
        // 枚举ordinal值按定义顺序递增,直接比较即可判断前进后退
        val isForward = current.ordinal > last!!.ordinal
        val targetFragment = when(current) {
            Destination.FIRST_SCREEN -> FirstScreenFragment()
            Destination.SECOND_SCREEN -> SecondScreenFragment()
            Destination.THIRD_SCREEN -> ThirdScreenFragment()
            Destination.FOURTH_SCREEN -> FourthScreenFragment()
        }
        fragmentManager.navigateTo(targetFragment, isForward)
    }

3. 升级navigateTo函数支持动画

fun FragmentManager.navigateTo(fragment: Fragment, isForward: Boolean) {
    // 替换为你自己实现的动画资源即可
    val (enterAnim, exitAnim) = if (isForward) {
        R.anim.slide_in_right to R.anim.slide_out_left
    } else {
        R.anim.slide_in_left to R.anim.slide_out_right
    }
    beginTransaction()
        .setCustomAnimations(enterAnim, exitAnim)
        .replace(R.id.contentFragment, fragment)
        .commit()
}

这个方案完全在流层面处理历史记录逻辑,不需要在Activity定义额外全局变量,也不需要修改ViewModel的StateFlow定义,完全符合你预期的调用形式。

内容的提问来源于stack exchange,提问作者m.reiter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 13:57:04