繁体   English   中英

Jetpack 导航动画完整监听器

[英]Jetpack Navigation Animation Complete Listener

完成新的导航事件以更改状态栏颜色时,我正在尝试使用 Jetpack Navigation 库获取回调。

到目前为止,我发现navController.addOnDestinationChangedListener会在新导航开始时通知我,但在完成时不会通知我,这意味着进入/退出转换已完成。

有什么方法可以知道所有导航转换何时完成?

你可以使用这样的东西:

val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment)
navHostFragment?.childFragmentManager?.addOnBackStackChangedListener {
    val currentFragment = navHostFragment.childFragmentManager.fragments.firstOrNull()
    if (currentFragment is YourFragment) {
        // your code here  
    } 
}

我遇到了同样的问题,终于找到了解决方法。

这个想法是当当前片段的退出动画结束时,调用该片段的onDestroyView

所以只要进入和退出动画的持续时间相同,我们就可以使用这个方法作为回调。

class BaseFragment() {
    private var leavingDestination = false

    fun navigateNext() {
        leavingDestination = true
        findNavController().navigate(blaBlaBla)
    }

    fun onNavigationAnimationEnds() {
        TODO()
    }

    // We just need to add an extra check, to be sure that onNavigationAnimationEnds is not called on configuration change
    override fun onDestroyView() {
        if(leavingDestination) {
            onNavigationAnimationEnds()
            leavingDestination = false
        }
    }
}

我使用所描述的方法来调用返回/退出片段中的一些代码。 如果您需要在导航到的片段中进行回调,您可以只使用共享ViewModel 就像ActivityViewModelNavGraph 范围的 ViewModel

像这样的东西:

class FragmentA() {
    private val mainActivityViewModel by activityViewModels<MainActivityViewModel> { viewModelFactory }
    ...
    override fun onDestroyView() {
        if(leavingDestination) {
            mainActivityViewModel.onNavigationAnimationEnds()
            leavingDestination = false
        }
    }
}
...
class MainActivity() {
    private val _navigationAnimationEndsEvent = MutableLiveData(Event())
    val navigationAnimationEndsEvent: LiveData<Event>; get() = _navigationAnimationEndsEvent

    fun onNavigationAnimationEnds() {
        _navigationAnimationEndsEvent.value = Event()
    }
}
...
class FragmentB() {
    private val mainActivityViewModel by activityViewModels<MainActivityViewModel> { viewModelFactory }

    override fun onActivityCreated() {
        ...
        mainActivityViewModel.navigationAnimationEndsEvent.observe(viewLifecycleOwner, Observer {
            it.getContentIfNotHandled()?.let {
                onNavigationAnimationsEnds()
            }    
        })
    }

    private fun onNavigationAnimationEnds() {
        TODO()
    }    
}

我使用的事件类:

open class Event<out T>(private val content: T) {

    var hasBeenHandled = false; private set

    fun getContentIfNotHandled() = if (hasBeenHandled) null else {
        hasBeenHandled = true
        content
    }

    fun peekContent(): T = content
}

PS:我尝试覆盖 onCreateAnimation/onCreateAnimator 函数并向它们添加侦听器,但它们从未被调用。

你可以参考这个答案来实现它。 简而言之,作为一种变通方法,您可以在事务开始时为动画添加一些延迟。

如答案中所述; 当您单击“导航到 X 片段”按钮时,片段替换开始。 所以延迟仅在片段交易动画中而不是在替换中

通过在 res 文件夹下的anim文件夹中的 your_anim_name.xml 文件中添加android:startOffset="300"来为动画添加延迟。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<alpha
    android:startOffset="300"
    android:fromAlpha="0.0"
    android:toAlpha="1.0"
    android:duration="400"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    />
<translate
    android:startOffset="300"
    android:fromYDelta="100%"
    android:toYDelta="0%"
    android:duration="400"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    />

答案很简单,就像“abc”:为了在过渡结束后做一些工作,在Fragment.View上添加一个监听器

例如,如果我们需要在当前Fragment绘制并呈现在屏幕上后才跳转到另一个Destination ,只需将此钩子放在 onResume 回调中:

override fun onResume() {
    super.onResume()
    view?.animation?.setAnimationListener(object: Animation.AnimationListener {
        override fun onAnimationRepeat(animation: Animation?) {}
        override fun onAnimationStart(animation: Animation?) {}
        override fun onAnimationEnd(animation: Animation?) {
            // Do the navigation or whatever you want
        }
    })
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM