在Android中为animation片段事务设置“z”索引或相机

我试图animation两个片段之间的交易,这个代码: 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指数应用于animation师吗?
  • 或者,我可以提供一个animation类,而不是包含animation的XML文件来animation片段转换?

谢谢。

编辑:检查差异。 在这里输入图像说明

Solutions Collecting From Web of "在Android中为animation片段事务设置“z”索引或相机"

为了实现你想要的,你需要在animation师中做更多的事情:

  • 使用不是默认值的透视图旋转视图(放置在视图中间)
  • 旋转时翻译视图

在这两种情况下,您都需要知道视图的大小,因此我build议您创build自定义布局组件,将其用作片段的根目录,从而暴露出一组属性,您可以在xml中使用不同的对象生成器来设置animation效果。

组件应该是这样的:

 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; } } } 

您的animation文件将如下所示:

 <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" /> 

当然你可以用flipLeftOutflipRightInflipRightOut来改变flipLeftIn ,以便将animation应用到不同的属性。

在你的Activity你可以像往常一样在片段事务中设置自定义animation,指定你之前定义的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定义的维度值来设置枢轴/转换并不像上面所示的解决scheme那样具有可扩展性。

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

翻转少倾斜

我试图按照a.bertucci的答案,但animation不起作用,我不知道为什么…我对这个世界有点新,有点难以理解自定义FlippableFrameLayout的情况。

但是从他对“相机距离”的回答中得到启发,我发现我只需要在缩放属性上再添加一个animation即可。 (即scaleX和scaleY)

因此, 在这里 , 一切与 官方教程 相同 ,你只需要修改animationxml文件,以达到预期的效果:

对于left_out.xmlright_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.xmlright_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)来调整“相机距离”。