如何获取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
相关产品推荐
相关产品推荐

