【问题标题】:Flip animation in Android for a Fragment transaction setting a "z" index or a camera在 Android 中为 Fragment 事务设置“z”索引或相机的翻转动画
【发布时间】:2017-08-04 10:00:23
【问题描述】:

我正在尝试使用以下代码对两个片段之间的事务进行动画处理: http://developer.android.com/training/animation/cardflip.html

但结果正是这样:http://developer.android.com/training/animation/anim_card_flip.mp4

但是,我想要这个结果:https://www.youtube.com/watch?v=52mXHqX9f3Y

不同之处在于,即使两者都旋转 180º,第二个使用不同的相机(Z 轴)进行旋转。

所以问题是:

  • 我可以将 Z-Index 应用于对象动画师吗?
  • 或者,我是否可以提供一个动画类而不是包含动画的 XML 文件来为片段过渡设置动画?

谢谢。

编辑:检查差异。

【问题讨论】:

  • 你为什么不直接使用他在那个 YouTube 剪辑中引用的 github 上的代码? genzeb.github.io/flip
  • 它使用了一个动画对象,我不能在片段转换中使用 AFAIK
  • 这很难解释。视图翻转的那一刻,是在这两个图像上捕获的。左侧:本文答案中的示例。右侧,iOS 动画。如您所见,左角永远不会像 iOS 示例那样深。
  • 请检查以下答案中的 youtube 链接
  • aha - 你应该把这样的链接放到你的问题中 - 这样会更容易理解。祝你好运,我期待阅读 a 的最终解决方案。

标签: android animation android-fragments


【解决方案1】:

要实现您想要的,您需要在动画师中再做两件事:

  • 使用非默认枢轴旋转视图(放置在视图中间)
  • 旋转时平移视图

在这两种情况下,您都需要知道视图的大小,因此我建议您创建自定义布局组件以用作片段的根,公开一组属性,您可以在您的内部使用不同的objectanimator 进行动画处理xml。

组件应如下所示:

public class FlippableLayout extends FrameLayout {

    private FlipEvaluator flipRightInEvaluator;
    private FlipEvaluator flipRightOutEvaluator;
    private FlipEvaluator flipLeftInEvaluator;
    private FlipEvaluator flipLeftOutEvaluator;

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

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

    private void init() {
        setCameraDistance(getCameraDistance() * 10); // reduces perspective skewing
        flipRightInEvaluator = new FlipEvaluator(
                1f, .5f, // pivotX/pivotY
                -1f, 0f, // translationX start/end
                -180, 0, // rotationY start/end
                0f, 1f); // alpha start/end
        flipRightOutEvaluator = new FlipEvaluator(
                0f, .5f,
                0f, 1f,
                0, 180,
                1f, 0f);
        flipLeftInEvaluator = new FlipEvaluator(
                .0f, .5f,
                1f, 0f,
                180, 0,
                0f, 1f);
        flipLeftOutEvaluator = new FlipEvaluator(
                1f, .5f,
                0f, -1f,
                0, -180,
                1f, 0f);
    }

    public void setFlipRightIn(float value) {
        evaluateUsing(flipRightInEvaluator, value);
    }

    public void setFlipRightOut(float value) {
        evaluateUsing(flipRightOutEvaluator, value);
    }

    public void setFlipLeftIn(float value) {
        evaluateUsing(flipLeftInEvaluator, value);
    }

    public void setFlipLeftOut(float value) {
        evaluateUsing(flipLeftOutEvaluator, value);
    }

    private void evaluateUsing(FlipEvaluator evaluator, float value) {
        float cappedValue = Math.min(1f, Math.max(0f, value));
        setPivotX(getWidth() * evaluator.getPivotX());
        setPivotY(getHeight() * evaluator.getPivotY());
        setAlpha(evaluator.getAlpha(cappedValue));
        setTranslationX(getWidth() * evaluator.getTranslationX(cappedValue));
        setRotationY(evaluator.getRotationY(cappedValue));
    }

    private static class FlipEvaluator {
        private final float pivotX;
        private final float pivotY;
        private final float startTranslationX;
        private final float endTranslationY;
        private final float startRotationY;
        private final float endRotationY;
        private final float startAlpha;
        private final float endAlpha;

        /**
         * Simple evaluator holding all the start/end values for a flip animation.
         *
         * @param pivotX value between 0 and 1, where 0 is the left border and 1 is the right border of the target
         * @param pivotY value between 0 and 1, where 0 is the top border and 1 is the bottom border of the target
         * @param startTranslationX value between 0 and 1, where 1 is the width of the target
         * @param endTranslationY value between 0 and 1, where 1 is the width of the target
         * @param startRotationY value between -180 and 180
         * @param endRotationY value between -180 and 180
         * @param startAlpha initial alpha
         * @param endAlpha final alpha
         */
        private FlipEvaluator(float pivotX, float pivotY,
                              float startTranslationX, float endTranslationY,
                              float startRotationY, float endRotationY,
                              float startAlpha, float endAlpha) {
            this.pivotX = pivotX;
            this.pivotY = pivotY;
            this.startTranslationX = startTranslationX;
            this.endTranslationY = endTranslationY;
            this.startRotationY = startRotationY;
            this.endRotationY = endRotationY;
            this.startAlpha = startAlpha;
            this.endAlpha = endAlpha;
        }

        public float getPivotX() {
            return pivotX;
        }

        public float getPivotY() {
            return pivotY;
        }

        public float getTranslationX(float t) {
            return startTranslationX + (endTranslationY - startTranslationX) * t;
        }

        public float getRotationY(float t) {
            return startRotationY + (endRotationY - startRotationY) * t;
        }

        public float getAlpha(float t) {
            return t < .5f ? startAlpha : endAlpha;
        }

    }

}

您的动画文件将如下所示:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:valueFrom="0"
        android:valueTo="1"
        android:propertyName="flipLeftIn"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:duration="1000" />

当然,您可以将flipLeftIn 更改为flipLeftOut、flipRightIn 或flipRightOut,以便将动画师应用于不同的属性。

在您的Activity 中,您可以像往常一样在片段事务中设置自定义动画,指定您之前定义的 XML:

    ....
    getFragmentManager()
            .beginTransaction()
            .setCustomAnimations(
                    R.animator.card_flip_right_in, R.animator.card_flip_right_out,
                    R.animator.card_flip_left_in, R.animator.card_flip_left_out)
    ....

另一种方法是在 XML 中完成所有操作,但使用通过 XML 定义的维度值设置数据透视/转换的可扩展性不如上面显示的解决方案。

编辑 要减少相机距离,您可以在 API>12 上轻松使用View.setCameraDistance()。我更新了包含此更改的 sn-p。

【讨论】:

  • 请检查我对另一个答案的评论。
  • 当然是在开始将我的答案放在这里之前。我检查了下面链接的视频,我发布的解决方案提供了与 ~3:10 显示的相同效果。您可以看到视图的垂直边缘不像 Vikram 的解决方案那样沿 Z “推动”,而是始终保持在视口的边缘。可能您想更好地查看发布的 gif,并且可能自己尝试代码。
  • 你好。它相当好,但请。检查我在问题中的编辑。感谢您的努力。
  • 现在我明白了,谢谢。您想要的是减少透视引起的倾斜效果。不幸的是,我不久前遇到了同样的问题,并没有找到任何方法来更改 Camera 类使用的深度。我最终得到的是使用Matrix 设施实现我自己的倾斜。我会尝试修改我的解决方案来解决这个问题。
  • 原来有一种方法可以调整相机距离developer.android.com/reference/android/view/…它是API 12+ tho。我会相应地更新我的答案。
【解决方案2】:

我试图按照 a.bertucci 的回答,但动画不起作用,我不知道为什么......我对这个世界有点陌生,有点难以理解发生了什么自定义 FlippableFrameLayout。

但是受到他关于相机距离的回答的启发,我发现我只需要在 scale 属性上再添加一个动画。 (即 scaleX 和 scaleY)

因此,其他一切都与official tutorial here相同,你只需要修改animator xml文件即可达到预期效果:

对于 left_out.xml 和 right_out.xml,添加以下内容:

    <objectAnimator
    android:valueFrom="1f"
    android:valueTo="0.5f"
    android:propertyName="scaleX"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:duration="@integer/card_flip_time_half" />

<objectAnimator
    android:valueFrom="1f"
    android:valueTo="0.5f"
    android:propertyName="scaleY"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:duration="@integer/card_flip_time_half" />

对于 left_in.xml 和 right_in.xml,添加以下内容:

    <objectAnimator
    android:valueFrom="0.5f"
    android:valueTo="1.0f"
    android:propertyName="scaleX"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:startOffset="@integer/card_flip_time_half"
    android:duration="@integer/card_flip_time_half" />

<objectAnimator
    android:valueFrom="0.5f"
    android:valueTo="1.0f"
    android:propertyName="scaleY"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:startOffset="@integer/card_flip_time_half"
    android:duration="@integer/card_flip_time_half" />

当然你也可以在这里修改valueFrom和valueTo(我用的是0.5f),来调整“相机距离”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    相关资源
    最近更新 更多