使用 Android 导航组件对片段过渡进行动画处理时发生 Z-Index 冲突
Z-Index conflict when animating fragment transition using the Android Navigation component
我正在尝试使用 Android Navigation 而不是片段交易。然而,有一个问题开始变得麻烦。在为 Enter Animation
使用滑入动画后,新片段将位于当前片段下方。请务必观看以下视频以查看正在运行的错误。
https://youtu.be/gFnXiEyiypM
该错误似乎不是来自 Navigation
组件,尽管针对此特定问题引入的 hacky 解决方案 (this and this) 在 Navigation
被使用。
在发布官方修复程序之前,是否没有解决此问题的方法?
很遗憾,Google 尚未解决此问题。已在此处报告:https://issuetracker.google.com/issues/79443865
我很难理解像 Google 这样的公司为何无法提供他们在 Material 指南中告诉我们要做的事情。
在 Google 发布官方修复之前,这个问题有一个 hacky 修复。解决方案是使用以下代码覆盖 onCreateAnimation
:
class BaseFragment : Fragment() {
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
if (nextAnim == R.anim.fragment_enter) {
val nextAnimation = AnimationUtils.loadAnimation(context, nextAnim)
nextAnimation.setAnimationListener(object : Animation.AnimationListener {
private var startZ = 0f
override fun onAnimationStart(animation: Animation) {
view?.apply {
startZ = ViewCompat.getTranslationZ(this)
ViewCompat.setTranslationZ(this, 10f)
}
}
override fun onAnimationEnd(animation: Animation) {
// Short delay required to prevent flicker since other Fragment wasn't removed just yet.
view?.apply {
this.postDelayed({ ViewCompat.setTranslationZ(this, startZ) }, 100)
}
}
override fun onAnimationRepeat(animation: Animation) {}
})
return nextAnimation
} else {
return null
}
}
}
我正在尝试使用 Android Navigation 而不是片段交易。然而,有一个问题开始变得麻烦。在为 Enter Animation
使用滑入动画后,新片段将位于当前片段下方。请务必观看以下视频以查看正在运行的错误。
https://youtu.be/gFnXiEyiypM
该错误似乎不是来自 Navigation
组件,尽管针对此特定问题引入的 hacky 解决方案 (this and this) 在 Navigation
被使用。
在发布官方修复程序之前,是否没有解决此问题的方法?
很遗憾,Google 尚未解决此问题。已在此处报告:https://issuetracker.google.com/issues/79443865
我很难理解像 Google 这样的公司为何无法提供他们在 Material 指南中告诉我们要做的事情。
在 Google 发布官方修复之前,这个问题有一个 hacky 修复。解决方案是使用以下代码覆盖 onCreateAnimation
:
class BaseFragment : Fragment() {
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
if (nextAnim == R.anim.fragment_enter) {
val nextAnimation = AnimationUtils.loadAnimation(context, nextAnim)
nextAnimation.setAnimationListener(object : Animation.AnimationListener {
private var startZ = 0f
override fun onAnimationStart(animation: Animation) {
view?.apply {
startZ = ViewCompat.getTranslationZ(this)
ViewCompat.setTranslationZ(this, 10f)
}
}
override fun onAnimationEnd(animation: Animation) {
// Short delay required to prevent flicker since other Fragment wasn't removed just yet.
view?.apply {
this.postDelayed({ ViewCompat.setTranslationZ(this, startZ) }, 100)
}
}
override fun onAnimationRepeat(animation: Animation) {}
})
return nextAnimation
} else {
return null
}
}
}