Flip animation in Android to configure the transaction fragment "z" index or camera

I am trying to animate a transaction between two fragments using this code: http://developer.android.com/training/animation/cardflip.html

But the result is this: http://developer.android.com/training/animation/anim_card_flip.mp4

However, I need this result: https://www.youtube.com/watch?v=52mXHqX9f3Y

The difference is that even both of them rotate 180º, and the second with the other camera (Z-axis).

So the question is:

  • Can I apply a Z-Index to object animators?
  • Or can I provide an Animation class instead of an XML file that contains an animation to animate fragment transitions?

Thanks.

Edit: check the differences. enter image description here

+7
android animation android-fragments
source share
2 answers

To achieve what you want, you need to do two more things in your animators:

  • rotate the view using a point that is not standard by default (placed in the middle of the view).
  • translate view while spinning

In both cases, you need to know the size of your view, so I would recommend creating your own layout component, which will be used as the root of your fragments, exposing a set of properties that you can animate using different objectanimator inside your XML.

The component should look like this:

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

Your animation files will look like this:

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

Of course, you can change flipLeftIn to flipLeftOut , flipRightIn or flipRightOut to apply the animator to another property.

In Activity you can configure custom animation in a fragment transaction, as usual, by specifying previously defined XML files:

  .... 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) .... 

Flip example

Another approach is to do everything in XML, but setting up rotation / translation using a dimension value defined through XML is not as scalable as the solution shown above.

EDIT To reduce the distance to the camera, you can easily use View.setCameraDistance () in API> 12. I updated the fragment, including this change.

Flip with less skewing

+7
source share

I tried to execute a.bertucci answer, but the animation doesn’t work, I don’t know why ... I am a little new to this world, and it’s a little difficult for me to understand what is happening around the custom FlippableFrameLayout.

But, inspired by his response to the distance from the camera, I found that I just needed to overlay another animation on the scale property. (i.e. scaleX and scaleY)

Therefore, if everything else, like the official tutorial here , you just need to change the xml file animator to achieve the desired effect:

For left_out.xml and right_out.xml , add the following:

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

For left_in.xml and right_in.xml , add the following:

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

And of course, you can change the From and valueTo values ​​here (I used 0.5f) to adjust the "camera distance".

0
source share

All Articles