gpt4 book ai didi

android - 嵌套 fragment 转换不正确

转载 作者:IT老高 更新时间:2023-10-28 23:15:03 27 4
gpt4 key购买 nike

你好,堆栈溢出的好程序员!我在这个问题上度过了愉快的一周,现在非常绝望以寻求解决方案。

场景

我正在使用android.app.Fragment,不要与支持片段相混淆。

我有6个子片段,分别命名为:

  • FragmentOne
  • FragmentTwo
  • FragmentThree
  • FragmentA
  • FragmentB
  • FragmentC

  • 我有2个父片段,名为:
  • FragmentNumeric
  • FragmentAlpha

  • 我有1个 Activity 名为:
  • MainActivity

  • 它们的行为如下:
  • 子片段是仅显示 View 的片段,它们不显示也不包含片段。
  • 父片段用单个子片段填充整个 View 。他们能够用其他子片段替换该子片段。
  • 该 Activity 使用父片段填充了大部分 View 。可以将其替换为其他父片段。
    因此,在任何时候屏幕上都只会显示一个子片段。

  • 您可能已经猜到了
    FragmentNumeric显示子片段 FragmentOneFragmentTwoFragmentThree
    FragmentAlpha显示子片段 FragmentAFragmentBFragmentC

    问题

    我正在尝试过渡/设置父片段和子片段的动画。子片段会平稳过渡,并且符合预期。但是,当我过渡到新的父片段时,它看起来很糟糕。子片段看起来像是从其父片段运行独立的过渡。子片段看起来也像从父片段中删除了一样。可以在这里gift_a查看它的gif图像。请注意当我单击“显示Alpha”时会发生什么。

    我能找到的最接近的问题和答案在这里: https://imgur.com/kOAotvk但是所有答案都不令人满意。

    Animator XML文件

    我有以下动画师效果(对于测试目的,持续时间很长):

    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>

    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>

    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>

    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>

    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>

    MainActivity.kt

    要考虑的事情:第一个父片段FragmentNumeric没有输入效果,因此它始终准备好 Activity ,并且没有退出效果,因为什么都没有退出。我也使用 FragmentTransaction#add,因为FragmentAlpha使用 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()
    }
    }
    }

    片段数值

    在快速显示其第一个子片段方面,该 Activity 与该 Activity 具有相同的作用。

    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()
    }
    }
    }
    }

    其他片段

    FragmentAlpha遵循与FragmentNumeric相同的模式,分别用片段A,B和C替换片段一,片段二和片段三。

    子片段只是显示以下XML View ,并动态设置其文本和按钮单击监听器,以从父片段或 Activity 中调用函数。

    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>

    使用 Dagger 和某些契约(Contract),我可以通过以下操作使子片段回调到其父片段并托管 Activity :

    FragmentOne设置按钮单击监听器来执行以下操作:
    (parentFragment as FragmentNumeric).showFragmentTwo()

    FragmentTwo设置按钮单击监听器以执行以下操作:
    (parentFragment as FragmentNumeric).showFragmentThree()

    FragmentThree不同,它将设置点击监听器来做:
    (activity as MainActivity).showFragmentAlpha()

    有人对此问题有解决方案吗?

    更新1

    我已按要求添加了一个示例项目: Nested fragments disappear during transition animation

    它和原始视频中的一个区别是父片段不再使用具有xFraction属性的 View 。因此,看起来Enter动画不再具有这种重叠效果。但是,它仍会从父级中删除子级片段,并对其进行动画处理。动画完成后,片段三立即替换为片段A。

    更新2

    父片段 View 和子片段 View 都使用xFraction属性。关键是在父级设置动画时抑制子级动画。

    最佳答案

    我想我已经找到一种使用Fragment#onCreateAnimator解决此问题的方法。转换的Gif可以在这里查看:https://imgur.com/94AvrW4

    我进行了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()
    }

    bool 值是在不同的场景中设置的,这些场景在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)
    }

    万一有人找到更好的方法,这个问题将悬而未决。

    关于android - 嵌套 fragment 转换不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46859132/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com