zaf*_*ani 18 android android-fragments fragmenttransaction android-nested-fragment fragment-animation
你好堆栈溢出的程序员!我已经度过了这个问题的好一周,现在我非常渴望一个解决方案.
我正在使用android.app.Fragment,不要与支持片段混淆.
我有6个子片段命名为:
FragmentOneFragmentTwoFragmentThreeFragmentAFragmentBFragmentC我有2个父片段命名:
FragmentNumericFragmentAlpha我有1个名为的活动:
MainActivity他们表现如下:
你可能已经猜到了,
FragmentNumeric显示子片段FragmentOne,FragmentTwo和FragmentThree.
FragmentAlpha显示子片段FragmentA,FragmentB和FragmentC.
我正在尝试过渡/动画父母和子女片段.儿童片段按预期顺利过渡.但是,当我转换到新的父片段时,它看起来很糟糕.子片段看起来像是从其父片段运行独立过渡.并且子片段看起来也像是从父片段中删除的.它的gif可以在这里查看https://imgur.com/kOAotvk.注意单击Show Alpha时会发生什么.
我能找到的最接近的问题和答案是:嵌套片段在过渡动画期间消失,但所有答案都不满意.
我有以下动画效果(持续时间很长,用于测试目的):
fragment_enter.xml
<?xml version="1.0" encoding="utf-8"?>
<set>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="xFraction"
android:valueFrom="1.0"
android:valueTo="0" />
</set>
Run Code Online (Sandbox Code Playgroud)
fragment_exit.xml
<?xml version="1.0" encoding="utf-8"?>
<set>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="xFraction"
android:valueFrom="0"
android:valueTo="-1.0" />
</set>
Run Code Online (Sandbox Code Playgroud)
fragment_pop.xml
<?xml version="1.0" encoding="utf-8"?>
<set>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="xFraction"
android:valueFrom="0"
android:valueTo="1.0" />
</set>
Run Code Online (Sandbox Code Playgroud)
fragment_push.xml
<?xml version="1.0" encoding="utf-8"?>
<set>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="xFraction"
android:valueFrom="-1.0"
android:valueTo="0" />
</set>
Run Code Online (Sandbox Code Playgroud)
fragment_nothing.xml
<?xml version="1.0" encoding="utf-8"?>
<set>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000" />
</set>
Run Code Online (Sandbox Code Playgroud)
需要考虑的事项:第一个父片段FragmentNumeric没有输入效果,所以它总是准备好活动,并且没有退出效果,因为没有任何东西正在退出.我也在使用FragmentTransaction#addFragmentAlpha使用的地方FragmentTransaction#replace
class MainActivity : AppCompatActivity {
fun showFragmentNumeric(){
this.fragmentManager.beginTransaction()
.setCustomAnimations(R.animator.fragment_nothing,
R.animator.fragment_nothing,
R.animator.fragment_push,
R.animator.fragment_pop)
.add(this.contentId, FragmentNumeric(), "FragmentNumeric")
.addToBackStack("FragmentNumeric")
.commit()
}
fun showFragmentAlpha(){
this.fragmentManager.beginTransaction()
.setCustomAnimations(R.animator.fragment_enter,
R.animator.fragment_exit,
R.animator.fragment_push,
R.animator.fragment_pop)
.replace(this.contentId, FragmentAlpha(), "FragmentAlpha")
.addToBackStack("FragmentAlpha")
.commit()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
showFragmentNumeric()
}
}
}
Run Code Online (Sandbox Code Playgroud)
在快速显示其第一个子片段方面与活动相同.
class FragmentNumeric : Fragment {
fun showFragmentOne(){
this.childFragmentManager.beginTransaction()
.setCustomAnimations(R.animator.fragment_nothing,
R.animator.fragment_nothing,
R.animator.fragment_push,
R.animator.fragment_pop)
.add(this.contentId, FragmentOne(), "FragmentOne")
.addToBackStack("FragmentOne")
.commit()
}
fun showFragmentTwo(){
this.childFragmentManager.beginTransaction()
.setCustomAnimations(R.animator.fragment_enter,
R.animator.fragment_exit,
R.animator.fragment_push,
R.animator.fragment_pop)
.replace(this.contentId, FragmentTwo(), "FragmentTwo")
.addToBackStack("FragmentTwo")
.commit()
}
fun showFragmentThree(){
this.childFragmentManager.beginTransaction()
.setCustomAnimations(R.animator.fragment_enter,
R.animator.fragment_exit,
R.animator.fragment_push,
R.animator.fragment_pop)
.replace(this.contentId, FragmentThree(), "FragmentThree")
.addToBackStack("FragmentThree")
.commit()
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (savedInstanceState == null) {
if (this.childFragmentManager.backStackEntryCount <= 1) {
showFragmentOne()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
FragmentAlpha遵循与FragmentNumeric相同的模式,分别用片段A,B和C替换片段一,二和三.
子片段只显示以下XML视图,并动态设置其文本和按钮单击侦听器,以从父片段或活动调用函数.
view_child_example.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<TextView
android:id="@+id/view_child_example_header"
style="@style/Header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/view_child_example_button"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
使用dagger和一些契约我让子片段回调到它们的父片段并通过执行如下操作来托管活动:
FragmentOne设置按钮单击侦听器:
(parentFragment as FragmentNumeric).showFragmentTwo()
Run Code Online (Sandbox Code Playgroud)
FragmentTwo设置按钮单击侦听器:
(parentFragment as FragmentNumeric).showFragmentThree()
Run Code Online (Sandbox Code Playgroud)
FragmentThree不同,它会将click监听器设置为:
(activity as MainActivity).showFragmentAlpha()
Run Code Online (Sandbox Code Playgroud)
有没有人有这个问题的解决方案?
我按要求添加了一个示例项目:https://github.com/zafrani/NestedFragmentTransitions
它与原始视频中的差异是父片段不再使用具有xFraction属性的视图.所以看起来输入动画不再具有重叠效果了.但它仍然会从父项中删除子片段并将它们并排放置.动画完成后,片段三立即替换为片段A.
父片段视图和子片段视图都使用xFraction属性.关键是在父动画动画时抑制子动画.
我想我已经找到了一种使用 Fragment#onCreateAnimator 来解决这个问题的方法。可以在此处查看过渡的 gif:https: //i.stack.imgur.com/NmeMo.jpg。
我制作了一个 PR 进行测试,到目前为止,它按我的预期工作,并且在配置更改后仍然存在并支持后退按钮。这是链接https://github.com/zafrani/NestedFragmentTransitions/pull/1/files#diff-c120dd82b93c862b01c2548bdcafcb20R25
父片段和子片段的 BaseFragment 正在为 onCreateAnimator() 执行此操作
override fun onCreateAnimator(transit: Int, enter: Boolean, nextAnim: Int): Animator {
if (isConfigChange) {
resetStates()
return nothingAnim()
}
if (parentFragment is ParentFragment) {
if ((parentFragment as BaseFragment).isPopping) {
return nothingAnim()
}
}
if (parentFragment != null && parentFragment.isRemoving) {
return nothingAnim()
}
if (enter) {
if (isPopping) {
resetStates()
return pushAnim()
}
if (isSuppressing) {
resetStates()
return nothingAnim()
}
return enterAnim()
}
if (isPopping) {
resetStates()
return popAnim()
}
if (isSuppressing) {
resetStates()
return nothingAnim()
}
return exitAnim()
}
Run Code Online (Sandbox Code Playgroud)
布尔值是在不同的场景中设置的,这些场景在 PR 中更容易看到。
动画功能有:
private fun enterAnim(): Animator {
return AnimatorInflater.loadAnimator(activity, R.animator.fragment_enter)
}
private fun exitAnim(): Animator {
return AnimatorInflater.loadAnimator(activity, R.animator.fragment_exit)
}
private fun pushAnim(): Animator {
return AnimatorInflater.loadAnimator(activity, R.animator.fragment_push)
}
private fun popAnim(): Animator {
return AnimatorInflater.loadAnimator(activity, R.animator.fragment_pop)
}
private fun nothingAnim(): Animator {
return AnimatorInflater.loadAnimator(activity, R.animator.fragment_nothing)
}
Run Code Online (Sandbox Code Playgroud)
如果有人找到更好的方法,我们将保留这个问题。
| 归档时间: |
|
| 查看次数: |
1204 次 |
| 最近记录: |