R.animator objectAnimators 不支持 Fragment add/remove 动画

R.animator with objectAnimators aren't working with Fragment add/remove animations

我不知道为什么这总是很难开始工作。我正在使用 AppCompat 库和 android.app.Fragment。我尝试添加动画以在 left/right 中滑动新片段(就像 iOS 那样),但是当添加片段时,它们会立即添加/删除,没有任何动画。

我做错了什么?

getFragmentManager()
    .beginTransaction()
    .setCustomAnimations(R.animator.slide_in_from_right, R.animator.slide_out_to_the_left)
    .add(R.id.navrootlayout, fragment)
    .addToBackStack(null)
    .commit();

res/animator/slide_in_from_right.xml

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

res/animator/slide_out_to_the_left.xml

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

我什至将动画的持续时间设置为 3000(即 3 秒),这样我就可以明确地看到它是否在使用,但实际上并没有。添加片段时根本没有任何动画。我拍下了它发生的屏幕视频,新片段立即出现(并最终消失)。

我发现我做错了什么。我从某处的示例中获取了动画 xml 文件,而该示例并没有提到我需要自己实现 xFraction 属性。我错误地认为这是一种内置行为,可以理解 xFraction 和 x 是相关的,类似于旧样式​​ res/anim 样式动画允许您使用百分比值作为动画的方式 start/end值。

但是,不。为此,您必须创建布局的子类并自己添加 xFraction 属性。我就是这样做的。

package com.mydomain.myapp;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

public class SlideableLayout extends RelativeLayout {


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

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

    public SlideableLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public float getXFraction() {
        final int width = getWidth();
        if (width != 0) {
            return getX() / getWidth();
        } else {
            return getX();
        }
    }

    public void setXFraction(float xFraction) {
        final int width = getWidth();
        if (width > 0) {
            setX(xFraction * width);
        } else {
            setX(-10000);
        }
    }
}

然后,对于我想要在屏幕上和屏幕外设置动画的每个片段,我使用 SlideableLayout 作为根布局。

<?xml version="1.0" encoding="utf-8"?>
<com.mydomain.myapp.SlideableLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/holo_blue_bright"
    >

</com.mydomain.myapp.SlideableLayout>