Android实现3D垂直翻转动画
在移动应用开发中,动画效果可以极大地提升用户体验,本文将详细介绍如何在Android中实现一个3D垂直翻转动画,使视图(如ImageView)能够像翻书页一样上下翻转,这个动画不仅具有视觉吸引力,还能为用户提供更直观的交互体验,我们将一步步展示如何通过XML文件和Java代码来实现这一动画效果。
动画资源文件定义
我们需要定义两个动画资源文件,分别用于控制图像的缩小、旋转和透明度变化。
card_flip_left_out.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-先缩小 --> <objectAnimator android:duration="200" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="0.8" /> <objectAnimator android:duration="200" android:propertyName="scaleY" android:valueFrom="1.0" android:valueTo="0.8" /> <!-再旋转 --> <objectAnimator android:duration="@integer/card_flip_time_full" android:interpolator="@android:interpolator/accelerate_decelerate" android:propertyName="rotationY" android:startOffset="200" android:valueFrom="0" android:valueTo="90" /> <!-同时透明度变化 --> <objectAnimator android:duration="@integer/card_flip_time_full" android:propertyName="alpha" android:startOffset="200" android:valueFrom="1.0" android:valueTo="0.0" /> </set>
card_flip_left_in.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-立即设置为透明 --> <objectAnimator android:duration="0" android:propertyName="alpha" android:valueFrom="1.0" android:valueTo="0.0" /> <!-旋转 --> <objectAnimator android:duration="@integer/card_flip_time_full" android:interpolator="@android:interpolator/accelerate_decelerate" android:propertyName="rotationY" android:valueFrom="-90" android:valueTo="0" /> <!-旋转一半的时间,逐渐显示 --> <objectAnimator android:duration="1" android:propertyName="alpha" android:startOffset="@integer/card_flip_time_half" android:valueFrom="0.0" android:valueTo="1.0" /> <!-最后放大 --> <objectAnimator android:duration="200" android:propertyName="scaleX" android:startOffset="@integer/card_flip_time_full" android:valueFrom="0.8" android:valueTo="1.0" /> <objectAnimator android:duration="200" android:propertyName="scaleY" android:startOffset="@integer/card_flip_time_full" android:valueFrom="0.8" android:valueTo="1.0" /> </set>
Java代码实现
我们在Activity中编写相应的Java代码来加载并执行这些动画,当用户点击ImageView时,将触发垂直翻转动画,如果需要更换图片,可以在动画结束时进行图片的替换。
ImageFlipActivity.java
package com.example.android.animationsdemo; import android.animation.Animator; import android.animation.AnimatorInflater; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; public class ImageFlipActivity extends Activity { private ImageView imageView; private int clickCount = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_image_flip); imageView = (ImageView) findViewById(R.id.iv_show); imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { playFlipAnimation(); } }); } private void playFlipAnimation() { clickCount++; AnimatorSet animatorSetOut = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.card_flip_left_out); final AnimatorSet animatorSetIn = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.card_flip_left_in); animatorSetOut.setTarget(imageView); animatorSetIn.setTarget(imageView); animatorSetOut.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // 翻转90度之后,换图 if (clickCount % 2 == 0) { imageView.setImageResource(R.drawable.image1); } else { imageView.setImageResource(R.drawable.image2); } animatorSetIn.start(); } }); animatorSetOut.start(); } }
在这个示例中,我们创建了一个ImageFlipActivity
类,该类包含一个ImageView
和一个点击监听器,当用户点击ImageView
时,会依次播放退出和进入的动画,根据点击次数的不同,图片会在两张图片之间切换。
3. 自定义Rotate3dAnimation类(可选)
如果你希望更灵活地控制动画,比如动态设置旋转角度、中心点等,可以实现一个自定义的Rotate3dAnimation
类,以下是一个简单的示例:
Rotate3dAnimation.java
package com.example.android.animationsdemo; import android.graphics.Camera; import android.graphics.Matrix; import android.view.animation.Animation; import android.view.animation.Transformation; public class Rotate3dAnimation extends Animation { private final float mFromDegrees; private final float mToDegrees; private final float mCenterX; private final float mCenterY; private final boolean mReverse; private Camera mCamera; public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX, float centerY, boolean reverse) { mFromDegrees = fromDegrees; mToDegrees = toDegrees; mCenterX = centerX; mCenterY = centerY; mReverse = reverse; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final float fromDegrees = mFromDegrees; final float toDegrees = mToDegrees; final float centerX = mCenterX; final float centerY = mCenterY; final Camera camera = mCamera; final Matrix matrix = t.getMatrix(); camera.save(); if (mReverse) { camera.translate(0.0f, centerX + width * 0.5f, -centerY height * 0.5f); camera.rotateY(fromDegrees); camera.rotateY(toDegrees fromDegrees); } else { camera.translate(0.0f, centerX + width * 0.5f, -centerY height * 0.5f); camera.rotateY(toDegrees); camera.rotateY(-fromDegrees); // Rotate in reverse direction for flip back effect } camera.getMatrix(matrix); // Apply the rotation to the matrix camera.restore(); // Restore the camera position before applying next transformation } }
使用此类时,你可以动态设置旋转的角度、中心点以及是否反向旋转。
Rotate3dAnimation rotate3dAnimation = new Rotate3dAnimation(0, 90, imageView.getWidth() / 2.0f, imageView.getHeight() / 2.0f, false); imageView.startAnimation(rotate3dAnimation);
这种方式提供了更高的灵活性,适用于更复杂的场景,可以在按钮点击事件中启动和停止旋转动画,以下是一个使用按钮控制旋转动画的示例:
public class Test3DRotateActivity extends Activity { private ImageView image; private Button start, stop; private Rotate3dAnimation rotation; private StartNextRotate startNext; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); image = (ImageView) findViewById(R.id.image); start = (Button) findViewById(R.id.start); stop = (Button) findViewById(R.id.stop); start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startRotation(0, 360); // 进行360度的旋转 } }); stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { image.clearAnimation(); // 停止当前的动画 } }); } private void startRotation(float start, float end) { final float centerX = image.getWidth() / 2.0f; final float centerY = image.getHeight() / 2.0f; rotation = new Rotate3dAnimation(start, end, centerX, centerY, false); rotation.setDuration(2000); rotation.setFillAfter(true); rotation.setInterpolator(new LinearInterpolator()); startNext = new StartNextRotate(); rotation.setAnimationListener(startNext); image.startAnimation(rotation); } private class StartNextRotate implements Animation.AnimationListener { public void onAnimationEnd(Animation animation) { image.startAnimation(rotation); } public void onAnimationRepeat(Animation animation) {} public void onAnimationStart(Animation animation) {} } } }``此示例展示了如何通过按钮控制3D旋转动画的启动和停止。
StartNextRotate内部类用于在动画结束时重新启动动画,从而实现连续旋转的效果,这种方法适用于需要频繁控制动画的场景,如游戏中的动画控制或复杂的用户交互界面,通过结合XML动画资源和自定义动画类,开发者可以根据需求灵活地实现各种复杂的动画效果,合理利用动画监听器(如
AnimatorListenerAdapter`)可以在动画的关键帧执行特定操作,进一步增强动画的表现力和互动性,无论是简单的视图转换还是复杂的3D动画,掌握这些技术都能帮助你在Android应用中创造出更加丰富和吸引人的用户体验。