android - 如何在Android上实现流畅的 fragment 交易动画

标签 android performance android-fragments fragmenttransaction

我主要使用 iOS,已经习惯了非常流畅的屏幕切换动画。我现在正在开发一个 Android 应用程序,我一生都无法获得 fragment 事务来顺利添加/替换 fragment 。

我的设置如下:MainActivity 的 xml 有一个 FrameLayout,我立即将 FragmentA 加载到 MainActivity OnCreate。然后,我的应用将 MainActivityFrameLayout 替换为 FragmentBFragmentC 等。所以我的整个应用程序只有 1 个 Activity 。

点击按钮时,我调用以下方法来添加/替换当前 fragment :

        getFragmentManager()
            .beginTransaction()
            .setCustomAnimations(R.animator.slide_in, android.R.animator.fade_out, android.R.animator.fade_in, R.animator.slide_out)
            .addToBackStack(null)
            .add(R.id.fragment_1, fragment)
            .commit();

slide_in.xml 看起来像(slide_out.xml 显然相反):

 <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
            android:interpolator="@android:interpolator/linear"
            android:propertyName="xFraction"
            android:valueType="floatType"
            android:valueFrom="1.0"
            android:valueTo="0"
            android:duration="@android:integer/config_shortAnimTime"
        />
</set>

滑入和滑出我正在为 xFraction 设置动画,我将其子类化为 LinearLayout 这样做:

public class SlidingLinearLayout extends LinearLayout {

    private float yFraction = 0;
    private float xFraction = 0;

    public SlidingLinearLayout(Context context) {
        super(context);
    }

    public SlidingLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SlidingLinearLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    private ViewTreeObserver.OnPreDrawListener preDrawListener = null;

    public void setYFraction(float fraction) {

        this.yFraction = fraction;

        if (getHeight() == 0) {
            if (preDrawListener == null) {
                preDrawListener = new ViewTreeObserver.OnPreDrawListener() {
                    @Override
                    public boolean onPreDraw() {
                        getViewTreeObserver().removeOnPreDrawListener(preDrawListener);
                        setYFraction(yFraction);
                        return true;
                    }
                };
                getViewTreeObserver().addOnPreDrawListener(preDrawListener);
            }
            return;
        }

        float translationY = getHeight() * fraction;
        setTranslationY(translationY);
    }

    public float getYFraction() {
        return this.yFraction;
    }

    public void setXFraction(float fraction) {

        this.xFraction = fraction;

        if (getWidth() == 0) {
            if (preDrawListener == null) {
                preDrawListener = new ViewTreeObserver.OnPreDrawListener() {
                    @Override
                    public boolean onPreDraw() {
                        getViewTreeObserver().removeOnPreDrawListener(preDrawListener);
                        setXFraction(xFraction);
                        return true;
                    }
                };
                getViewTreeObserver().addOnPreDrawListener(preDrawListener);
            }
            return;
        }

        float translationX = getWidth() * fraction;
        setTranslationX(translationX);
    }

    public float getxFraction() {
        return xFraction;
    }
}

所以我的问题是大多数时候,当我最初点击一个按钮来添加/替换一个 fragment 时,我没有得到一个动画,它只是弹出到位。然而,当我按下后退按钮并且 fragment 从后台弹出时,动画按预期执行的次数多于不。我觉得这是尝试动画时初始化的问题。当 fragment 在内存中并在屏幕外动画时,它比创建新 fragment 然后在屏幕上动画要好得多。我很好奇其他人是否遇到过这种情况,如果遇到过,他们是如何解决的。

这是困扰我 Android 开发经验的一个烦恼,我真的很想放下它!任何帮助将不胜感激。谢谢!

最佳答案

根据我的经验,如果 fragment 在加载时做了太多工作,那么系统基本上会跳过进入动画而只显示 fragment 。在我的例子中,解决方案是在 onCreateAnimation 中创建一个动画监听器,以等待进入动画完成,然后再执行导致动画被跳过的过程密集型工作。

@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
    if (nextAnim == 0) {
        return super.onCreateAnimation(transit, enter, nextAnim);
    }

    Animation anim = android.view.animation.AnimationUtils.loadAnimation(getContext(), nextAnim);
    anim.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {}
        @Override
        public void onAnimationEnd(Animation animation) {
            // Do any process intensive work that can wait until after fragment has loaded
        }

        @Override
        public void onAnimationRepeat(Animation animation) {}
    });
    return anim;
}

关于android - 如何在Android上实现流畅的 fragment 交易动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30405355/

相关文章:

java - 无法从我的 fragment 中的自定义对话框中获取字符串值

java - 将可空值从 Activity 传递到 Fragment

android - 如何更改 NsdManager 使用的 android 设备名称?

android - 使用 Android 的 Algolia 和 Cloud Firestore?

android - 定期工作请求未在工作管理器中执行 doWork

C 动态分配速度问题

对象数据成员的 C++ 连续内存访问

Android App 安装脚 native 制/方法

c - 为什么多个 if 语句比执行 while 循环更快?

android - 遍历Fragment返回栈时如何刷新ActionBar导航项?