Фрагмент потерял анимацию перехода после изменения конфигурации - PullRequest
30 голосов
/ 12 января 2012

Я вставляю фрагменты в активность, используя этот код:

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 через кнопку Back сразу после запуска, тогда все в порядке, и я вижу анимацию затухания. Но если я поверну устройство и нажму кнопку «Назад», фрагмент исчезнет без анимации.

Это поведение 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}}
    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 ]

10 голосов
/ 05 октября 2013

В качестве обходного пути для этого вы можете использовать методы 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 голосов
/ 11 ноября 2012

Хорошо, это ошибка, которая также является проблемой для нативной библиотеки (не только для поддержки библиотеки).

Единственный обходной путь, который я могу предложить, - это создать свой собственный задний стек и затем обрабатывать onBack с помощью собственной пользовательской реализации, настраивая правильную анимацию, когда вы возвращаетесь через свой собственный стек.

1 голос
/ 04 марта 2016

Вы можете использовать onCreateAnimation плюс AnimationUtils для каждого фрагмента вместо транзакции .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);
    }
}
1 голос
/ 13 февраля 2013

Альтернативное предложение для решения этой проблемы - загрузить исходный код библиотеки поддержки и внести изменения, которые я предложил в дефекте (http://code.google.com/p/android/issues/detail?id=25994) самостоятельно, конечно, это означает, что вы сами должны поддерживать копию библиотеки поддержки).и неспособность использовать встроенную поддержку, однако это зависит от того, насколько важна эта проблема для вас.

0 голосов
/ 18 апреля 2016

Эта ошибка исправлена ​​несколько дней назад в новой библиотеке поддержки 23.3.0. https://code.google.com/p/android/issues/detail?id=25994#c36

...