片段在配置更改后丢失了过渡动画

时间:2012-01-12 15:17:03

标签: android animation fragment

我正在使用以下代码将片段插入到Activity中:

public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    FragmentManager fm = getFragmentManager();
    String tag = "simple";

    Fragment fr = fm.findFragmentByTag(tag);
    if (fr == null)
    {
        SimpleFragment simpleFragment = new SimpleFragment(); 
        FragmentTransaction transaction = fm.beginTransaction();
        transaction.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out,
                                        android.R.animator.fade_in, android.R.animator.fade_out);
        transaction.add(R.id.main_layout, simpleFragment, tag);
        transaction.addToBackStack(tag);
        transaction.commit();
    }
}

片段代码是:

public class SimpleFragment extends ListFragment 
{
    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
    {
        super.onActivityCreated(savedInstanceState);
        getView().setBackgroundColor(Color.YELLOW);
    }
}

当我在启动后通过Back按钮从backstack弹出片段时,一切都很好,我可以看到淡出动画。但是,如果我旋转设备并按“返回”按钮,则片段会在没有动画的情况下消失。

这是Android行为还是我做错了什么?

编辑: 似乎旋转后FragmentManager没有为BackStackEntry恢复动画(enterAnim,exitAnim,popEnterAnim和popExitAnim)。

FragmentManager转储(不带旋转):

Active Fragments in 4087d668:
  #0: SimpleFragment{408883b0 #0 id=0x7f050000 simple}
    mFragmentId=#7f050000 mContainerId#=7f050000 mTag=simple
    mState=4 mIndex=0 mWho=android:fragment:0 mBackStackNesting=1
    mAdded=true mRemoving=false mResumed=true mFromLayout=false mInLayout=false
    mHidden=false mDetached=false mRetainInstance=false mRetaining=false mHasMenu=false
    mFragmentManager=FragmentManager{4087d668 in ListViewFragmentsActivity{4087d588}}
    mImmediateActivity=my.app.ListViewFragmentsActivity@4087d588
    mActivity=my.app.ListViewFragmentsActivity@4087d588
    mNextAnim=17498112
    mContainer=android.widget.RelativeLayout@408876d8
    mView=android.widget.FrameLayout@40888a70
Added Fragments:
  #0: SimpleFragment{408883b0 #0 id=0x7f050000 simple}
Back Stack:
  #0: android.app.BackStackRecord@408884b8
    mName=simple mIndex=0 mCommitted=true
    mEnterAnim=#10b0000 mExitAnim=#10b0001
    Operations:
      Op #0:
        cmd=1 fragment=SimpleFragment{408883b0 #0 id=0x7f050000 simple}
    enterAnim=17498112 exitAnim=17498113
    popEnterAnim=17498112 popExitAnim=17498113
Back Stack Indices:
  #0: android.app.BackStackRecord@408884b8
FragmentManager misc state:
  mCurState=5 mStateSaved=false mDestroyed=false

FragmentManager转储(旋转后):

Active Fragments in 40877f38:
  #0: SimpleFragment{40878858 #0 id=0x7f050000 simple}
    mFragmentId=#7f050000 mContainerId#=7f050000 mTag=simple
    mState=4 mIndex=0 mWho=android:fragment:0 mBackStackNesting=1
    mAdded=true mRemoving=false mResumed=true mFromLayout=false mInLayout=false
    mHidden=false mDetached=false mRetainInstance=false mRetaining=false mHasMenu=false
    mFragmentManager=FragmentManager{40877f38 in ListViewFragmentsActivity{40877e58}}
    mImmediateActivity=my.app.ListViewFragmentsActivity@40877e58
    mActivity=my.app.ListViewFragmentsActivity@40877e58
    mContainer=android.widget.RelativeLayout@4087ed50
    mView=android.widget.FrameLayout@4087fc00
Added Fragments:
  #0: SimpleFragment{40878858 #0 id=0x7f050000 simple}
Back Stack:
  #0: android.app.BackStackRecord@40878a78
    mName=simple mIndex=0 mCommitted=false
    Operations:
      Op #0:
        cmd=1 fragment=SimpleFragment{40878858 #0 id=0x7f050000 simple}
Back Stack Indices:
  #0: android.app.BackStackRecord@40878a78
FragmentManager misc state:
  mCurState=5 mStateSaved=false mDestroyed=false

5 个答案:

答案 0 :(得分:10)

作为解决方法,您可以在片段中使用onCreateAnimator / onCreateAnimation方法。

例如,对于本机片段实现:

@Override
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
    if (enter) {
        return AnimatorInflater.loadAnimator(getActivity(), R.animator.slide_in_top);
    } else {
        return AnimatorInflater.loadAnimator(getActivity(), R.animator.fade_out);
    }
}

使用Animation支持库片段的相同技术。在这种情况下,您还可以根据片段状态和/或参数更好地控制播放动画的方式。

答案 1 :(得分:2)

好的,这是一个错误,也是本机库(不仅是支持库)的问题。

我建议的唯一解决方法是创建自己的后台堆栈,然后使用自己的自定义实现处理onBack,并在返回自己的堆栈时设置正确的动画。

答案 2 :(得分:1)

解决此问题的另一个建议是下载支持库的源代码并自行进行我在缺陷(http://code.google.com/p/android/issues/detail?id=25994)中建议的更改,当然这意味着自己维护一个支持库的副本并且无法使用本机支持,但这取决于此问题对您的重要程度。

答案 3 :(得分:1)

您可以为每个片段使用onCreateAnimation plus AnimationUtils,而不是transaction.setCustomAnimations(..)。同样要在恢复期间跳过动画,请考虑一下boleean flag。

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    mIsRestoring = savedInstanceState != null;
    ...
}

@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
    if (mIsRestoring) {
        mIsRestoring = false;
        return null;
    }
    if (enter) {
        return AnimationUtils.loadAnimation(getContext(), R.anim.enter_from_right);
    } else {
        return AnimationUtils.loadAnimation(getContext(), R.anim.exit_to_left);
    }
}

答案 4 :(得分:0)

此错误几天前在新的支持库23.3.0中得到修复。 https://code.google.com/p/android/issues/detail?id=25994#c36