如何使用Navigation组件监听Android片段过渡完成?

5

我有一个碎片(fragment),它会加载大量数据并将其显示在recyclerView中。 如果我直接打开此碎片而不等待转换完成,则转换将变得卡顿,因为线程受到recyclerView更新数据的限制。

因此,我希望将此数据更新延迟到碎片转换完成后再执行。

但可悲的是,我还没有找到任何监听碎片转换完成的方法,因此我当前的解决方案是使用Handler()延迟数据更新数毫秒,但我认为这是一种很别扭和不优雅的解决方案。

Handler().postDelayed({
//do something
}, 500)

我需要帮助知道应该调用哪个方法来监听片段转换完成。谢谢你!

3个回答

2
碎片提供了两种避免这个问题的方法:
  1. 您可以通过延迟转换来等待数据加载完成后再开始转换。这确保了您的RecyclerView已经填充了可用于共享元素转换等的数据。这是一般推荐的做法,可以确保在所有版本的碎片中实现平滑的转换。

  2. 使用Fragment 1.3.0或更高版本时,直到任何转换或动画(特别是不是动画)完成后,您的碎片才会达到恢复状态。这使得您可以使用onResume()作为信号,表明您的转换已经完成。


1
嗨,Ian!我正在使用Fragment 1.3.1,发现onResume()似乎在navigate()之后立即被调用。我也尝试使用版本1.3.0,但那也不起作用。 - Max
你是否正在使用动画器?动画效果?框架转换?AndroidX 转换?如果是最后一种,请确保你正在使用最新版本的 AndroidX 转换(Transition 1.4.1)。 - ianhanniballake
我正在使用自定义的滑动动画与Android导航组件。 - Max
1
正如我在答案中非常明确地提到的那样,动画是 onResume() 时间的一个例外(您考虑使用 Slide Transition 吗?)。推迟可以与任何类型的效果一起使用,包括动画,并允许您在开始动画之前完全加载数据。这就是为什么我首先提到了这种方法 :-) - ianhanniballake
谢谢您澄清了这个问题 :-) - Max
如果一些操作需要在转换结束后立即执行怎么办?具体来说,我不需要加载数据,但需要更改GLSurfaceView的可见性。如果在转换仍在执行时GL视图可见 - 它会出现在所有视图层次结构的顶部,并且还会覆盖从中退出的片段。 - A. Petrov

2

通过遵循这篇答案中介绍的onCreateAnimation方法,我成功地实现了它。

override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
    val anim: Animation = AnimationUtils.loadAnimation(activity, nextAnim)
    anim.setAnimationListener(object : Animation.AnimationListener {
        override fun onAnimationStart(animation: Animation?) {}
        override fun onAnimationRepeat(animation: Animation?) {}
        override fun onAnimationEnd(animation: Animation?) {
            if (enter) {
                //load and update recyclerView here
            }
        }
    })
    return anim
}

我不确定我理解这个问题,但我们可以使用计时器而不是延迟吗? - shn
1
@Furkan,计时器/延迟等的问题在于当我改变过渡持续时间时,它会出现故障,屏幕再次变得卡顿。我需要确保过渡保持平滑,无论我如何调整值。 - Fugogugo

0
如果你必须使用动画效果,而不是转换或者动画器,那么你可以将动画持续时间提取为一个整数资源,并将动画持续时间设置为该资源。
<!-- values/durations.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="animation_duration">220</integer>
</resources>


<!-- anim/transition.xml -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false" >
    <alpha android:duration="@integer/animation_duration" android:fromAlpha="0.0" android:toAlpha="1.0" />
</set>

然后在您的片段中检索它:

val animationDuration = requireContext().resources.getInteger(R.integer.animation_duration)
Handler().postDelayed({
//do something
}, animationDuration)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接