После изменения конфигурации фрагмент потерял переходную анимацию
Я вставляю фрагменты в 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);
}
}
Когда я вывожу фрагмент из backstack через кнопку "Назад" сразу после запуска, тогда все в порядке, и я вижу, как исчезает анимация. Но если я вращаю устройство и нажимаю кнопку "Назад", фрагмент исчезает без анимации.
Является ли это поведение Android или я что-то не так?
EDIT:
Кажется, что после ротации FragmentManager не восстанавливал анимацию (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}}
[email protected]
[email protected]
mNextAnim=17498112
[email protected]
[email protected]
Added Fragments:
#0: SimpleFragment{408883b0 #0 id=0x7f050000 simple}
Back Stack:
#0: [email protected]
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: [email protected]
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}}
[email protected]
[email protected]
[email protected]
[email protected]
Added Fragments:
#0: SimpleFragment{40878858 #0 id=0x7f050000 simple}
Back Stack:
#0: [email protected]
mName=simple mIndex=0 mCommitted=false
Operations:
Op #0:
cmd=1 fragment=SimpleFragment{40878858 #0 id=0x7f050000 simple}
Back Stack Indices:
#0: [email protected]
FragmentManager misc state:
mCurState=5 mStateSaved=false mDestroyed=false
Ответы
Ответ 1
В качестве обходного пути для этого вы можете использовать методы 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);
}
}
Такая же методика для фрагментов библиотеки поддержки с анимацией. В этом случае вы также имеете больший контроль над тем, как вы хотите играть в анимацию в зависимости от состояния фрагмента и/или аргументов.
Ответ 2
Хорошо, так что это ошибка, которая также является проблемой для родной библиотеки (а не только для библиотеки поддержки).
Единственное обходное решение, которое я могу предложить, - создать свой собственный задний стек, а затем обработать onBack с вашей собственной настраиваемой реализацией, настроив правильную анимацию, когда вы вернетесь через свой собственный стек.
Ответ 3
Альтернативное предложение по решению этой проблемы - загрузить источник для библиотеки поддержки и внести изменения, которые я предложил в дефект (http://code.google.com/p/android/issues/detail?id=25994), конечно, это означает, что вы сами поддерживаете копию библиотеки поддержки и не можете использовать встроенную поддержку, но это зависит от того, насколько важна эта проблема для вас.
Ответ 4
Вы можете использовать onCreateAnimation plus AnimationUtils для каждого фрагмента вместо transaction.setCustomAnimations(..). Также, чтобы пропустить анимацию во время восстановления, подумайте о более голубом флаге.
@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);
}
}
Ответ 5
Эта ошибка исправлена несколько дней назад в новой библиотеке поддержки 23.3.0
.
https://code.google.com/p/android/issues/detail?id=25994#c36