configuration更改后,片段丢失了过渡animation

我使用以下代码将Fragments插入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); } } 

当启动后通过后退button从后台popup片段时,一切正常,我可以看到淡出animation。 但是,如果我旋转设备,然后按返回button然后片段消失,没有animation。

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

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

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 

Solutions Collecting From Web of "configuration更改后,片段丢失了过渡animation"

作为解决方法,您可以在片段中使用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代替支持库碎片的相同技术。 在这种情况下,根据片段状态和/或参数,还可以更好地控制播放animation的方式。

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

我可以build议的唯一解决方法是创build自己的后台堆栈,然后用自己的自定义实现来处理onBack,以便在您通过自己的堆栈返回时设置正确的animation。

解决此问题的另一个build议是下载支持库的源代码,并自行修改我在缺陷( http://code.google.com/p/android/issues/detail?id=25994 )中提出的更改,当然这意味着要自己维护一个支持库的副本,而不能使用本地支持,但是这取决于这个问题对您有多重要。

您可以使用onCreateAnimation加AnimationUtils为每个片段,而不是transaction.setCustomAnimations(..)。 还要在恢复时跳过animation,考虑一下boleean的标志。

 @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); } } 

这个bug在几天前在新的支持库23.3.0https://code.google.com/p/android/issues/detail?id=25994#c36