Jetpack 导航动画完整监听器

Posted

技术标签:

【中文标题】Jetpack 导航动画完整监听器【英文标题】:Jetpack Navigation Animation Complete Listener 【发布时间】:2019-11-27 05:30:13 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

你可以这样使用:

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  
     

【讨论】:

【参考方案2】:

您可以参考this answer 来实现它。简而言之,作为一种解决方法,您可以在事务开始时为您的动画添加一些延迟。

如答案中所述;当您单击“导航到 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"
    />

【讨论】:

【参考方案3】:

答案很简单,就像“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
        
    )

【讨论】:

【参考方案4】:

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

想法是当当前片段的退出动画结束时,调用该片段的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。喜欢ActivityViewModel 或NavGraph scoped 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

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

【讨论】:

很抱歉,这是非常糟糕的做法。

以上是关于Jetpack 导航动画完整监听器的主要内容,如果未能解决你的问题,请参考以下文章

Android jetpack compose中的按钮长按监听器

Jetpack Compose中判断和监听网络连接状态

Jetpack Compose中判断和监听网络连接状态

Android Jetpack WorkManager 设置TAG,监听任务执行 取消任务

Bootstrap Navbar随着smoothScroll消失

如何将事件监听器添加到动画变换旋转?