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中的按钮长按监听器
Android Jetpack WorkManager 设置TAG,监听任务执行 取消任务