android – setRetainInstance(true)setCustomAnimations(…)=每个方向更改的动画?

背景

我有一个活动,片段需要在创建时进行动画处理,但在方向改变时则不需要.

片段被动态插入到布局中,因为它是导航抽屉式活动的一部分.

问题

我想避免为配置更改重新创建片段,所以我在片段中使用了setRetainInstance.
它可以工作,但由于某种原因,每次旋转设备时动画也会重新启动.

我做了什么

我已将此添加到片段中:

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
}

这对活动:

final FragmentManager fragmentManager = getSupportFragmentManager();
    final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    MyFragment fragment= (MyFragment) fragmentManager.findFragmentByTag(MyFragment.TAG);
    if (fragment== null) {
        fragmentTransaction.setCustomAnimations(R.anim.slide_in_from_left,R.anim.slide_out_to_right);
        fragment= new MyFragment();
        fragmentTransaction
                .add(R.id.fragmentContainer,fragment,MyFragment.TAG).commit();
    }

fragment_container.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

我试过的

>我试图通过使用“替换”而不是“添加”来修复它.它没有帮助.
>我也尝试过总是执行片段的替换,如果片段已经存在,那就不用动画(在同一个片段上).
>如果我删除setRetainInstance调用,它可以工作,但我想避免重新创建片段.

>我该如何解决这个问题?
>为什么我仍然可以获得添加片段的动画?
>其他配置发生变化时会发生什么?

解决方法#1

这个解决方案通常有效,但它会给你试图实现的生命周期带来不好的结果:

MyFragment fragment= (MyFragment) fragmentManager.findFragmentByTag(MyFragment.TAG);
    if (MyFragment== null) {
        MyFragment= new MyFragment();
        fragmentManager.beginTransaction().setCustomAnimations(R.anim.slide_in_from_left,R.anim.slide_out_to_right)
                .replace(R.id.fragmentContainer,MyFragment.TAG).commit();
    } else {
        //workaround: fragment already exists,so avoid re-animating it by quickly removing and re-adding it:
        fragmentManager.beginTransaction().remove(fragment).commit();
        final Fragment finalFragment = fragment;
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                fragmentManager.beginTransaction().replace(R.id.fragmentContainer,finalFragment .TAG).commit();
            }
        });
    }

我仍然希望看到可以做什么,因为这会导致你不想发生的事情(例如onDetach for the fragment).

解决方法#2

解决此问题的一种方法是避免通过fragmentManager添加动画,并在片段生命周期内为视图本身执行此操作.
这是它的样子:

BaseFragment

@Override
public void onViewCreated(final View rootView,final Bundle savedInstanceState) {
    super.onViewCreated(rootView,savedInstanceState);
    if (savedInstanceState == null)
        rootView.startAnimation(AnimationUtils.loadAnimation(getActivity(),R.anim.slide_in_from_left));
}


@Override
public void onDestroyView() {
    super.onDestroyView();
    if (!getActivity().isChangingConfigurations())
        getView().startAnimation(AnimationUtils.loadAnimation(getActivity(),R.anim.fade_out));
}

解决方法

如果在旋转后重新创建片段,您如何覆盖 onCreateAnimation()方法并阻止动画发生?

如图所示:How to disable/avoid Fragment custom animations after screen rotation

编辑:这是一个示例代码

BaseFragment.java

...
private boolean mNeedToAvoidAnimation;

@Override
public void onDestroyView() {
    super.onDestroyView();
    mNeedToAvoidAnimation = true;
}

@Override
public Animation onCreateAnimation(int transit,boolean enter,int nextAnim) {
    // This avoids the transaction animation when the orienatation changes
    boolean needToAvoidAnimation = mNeedToAvoidAnimation;
    mNeedToAvoidAnimation = false;
    return needToAvoidAnimation ? new Animation() {
    } : super.onCreateAnimation(transit,enter,nextAnim);
}

此片段应该是此活动中所有片段将扩展的基础片段.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...