android 翻牌效果

xiaoxiao2025-07-06  5

翻牌效果网上很多,一搜一大把,有各种实现方法,我就记录下我觉得简单效果好的方法,一个是属性动画ObjectAnimator实现,还有一个是android.graphics.Camera(不是拍照录像的Camera),我比较在意的是用Camera这个类实现的3d效果 网上的Camera例子基本都是用Rotate3dAnimation.java,我就随便拿了个进行测试,发现有bug,后来找到这篇文章安卓自定义View进阶-Matrix Camera,原来Rotate3dAnimation.java是一个演示demo,而这篇文章也把这个bug解决了,而且这篇文章里的推荐控件也很强大 我在Canvas内进行了简单的测试,看看Camera效果

Rotate3dView.java,翻转代码用的就是Rotate3dAnimation.java内的代码

public class Rotate3dView extends View { private Bitmap frontBitmap; private Bitmap backBitmap; private Paint paint; private Matrix matrix; private Camera camera; private float[] mValues = new float[9]; private float scale = 1; public Rotate3dView(Context context) { super(context); init(); } public Rotate3dView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } private void init(){ camera = new Camera(); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 8; frontBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_jn,options); backBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_m,options); paint = new Paint(); paint.setColor(Color.RED); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); matrix = new Matrix(); scale = getResources().getDisplayMetrics().density; } private int degrees = 0; public void setDegrees(int degrees) { this.degrees = degrees; postInvalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(getWidth() == 0 || getHeight() == 0){ return; } float centerX = getWidth()/2; float centerY = getHeight()/2; float left = centerX - frontBitmap.getWidth()/2; float top = centerY - frontBitmap.getHeight()/2; canvas.save(); camera.save(); matrix.setTranslate(0,0); if(degrees < 90){ camera.rotateY(degrees); }else{ camera.rotateY(degrees - 180); } camera.getMatrix(matrix); camera.restore(); matrix.getValues(mValues); //获取数值 mValues[6] = mValues[6]/scale; //数值修正 mValues[7] = mValues[7]/scale; //数值修正 matrix.setValues(mValues); //重新赋值 matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); // matrix.postTranslate(100, 100); canvas.setMatrix(matrix); if(degrees < 90){ canvas.drawBitmap(frontBitmap,left ,top,null); }else{ canvas.drawBitmap(backBitmap,left ,top,null); } canvas.restore(); canvas.drawRect(left,top,left+frontBitmap.getWidth(),top+frontBitmap.getHeight(),paint); canvas.drawLine(centerX,0,centerX,getHeight(),paint); canvas.drawLine(0,centerY,getWidth(),centerY,paint); } }

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.hyq.hm.testdraw.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#888"> <SeekBar android:id="@+id/seek_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:max="180"/> <com.hyq.hm.testdraw.Rotate3dView android:id="@+id/rotate_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </android.support.constraint.ConstraintLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity { private SeekBar seekBar; private Rotate3dView rotate3dView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); rotate3dView = findViewById(R.id.rotate_view); seekBar = findViewById(R.id.seek_bar); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { rotate3dView.setDegrees(progress); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } }

接下来贴翻牌动画代码,用属性动画ObjectAnimator实现的代码都注释掉了,可以把注释去掉,再把Rotate3dAnimation代码注释掉看看ObjectAnimator的效果,我觉得没有Rotate3dAnimation的好

Rotate3dAnimation.java

public class Rotate3dAnimation extends Animation { private final float mFromDegrees; private final float mToDegrees; private final float mCenterX; private final float mCenterY; private final float mDepthZ; private final boolean mReverse; private Camera mCamera; private float scale = 1; private int mXY; /** * 创建一个绕y轴旋转的3D动画效果,旋转过程中具有深度调节,可以指定旋转中心。 * * @param fromDegrees 起始时角度 * @param toDegrees 结束时角度 * @param centerX 旋转中心x坐标 * @param centerY 旋转中心y坐标 * @param depthZ 最远到达的z轴坐标 * @param reverse true 表示由从0到depthZ,false相反 */ public Rotate3dAnimation(Context context, float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ, boolean reverse,int xy) { mFromDegrees = fromDegrees; mToDegrees = toDegrees; mCenterX = centerX; mCenterY = centerY; mDepthZ = depthZ; mReverse = reverse; scale = context.getResources().getDisplayMetrics().density; mXY = xy; } @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; float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime); 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, 0.0f, mDepthZ * interpolatedTime); } else { camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); } if(mXY == 1){ camera.rotateX(degrees); }else{ camera.rotateY(degrees); } camera.getMatrix(matrix); camera.restore(); // 修正失真,主要修改 MPERSP_0 和 MPERSP_1 float[] mValues = new float[9]; matrix.getValues(mValues); //获取数值 mValues[6] = mValues[6]/scale; //数值修正 mValues[7] = mValues[7]/scale; //数值修正 matrix.setValues(mValues); //重新赋值 // 调节中心点 matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); } }

activity_rotate_3d.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="演示" android:onClick="startAnimation"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/front_view" android:layout_width="300dp" android:layout_height="300dp" android:layout_centerInParent="true" /> <ImageView android:id="@+id/back_view" android:layout_width="300dp" android:layout_height="300dp" android:layout_centerInParent="true" android:visibility="invisible" /> </RelativeLayout> </LinearLayout> </android.support.constraint.ConstraintLayout>

Rotate3dActivity.java

public class Rotate3dActivity extends AppCompatActivity { private ImageView[] imageViews = new ImageView[2]; private int index = 0; // private ObjectAnimator frontAnim; // private ObjectAnimator backAnim; private Animation frontAnim; private Animation backAnim; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_rotate_3d); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; imageViews[0] = findViewById(R.id.front_view); imageViews[0].setImageBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.ic_jn,options)); imageViews[1] = findViewById(R.id.back_view); imageViews[1].setImageBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.ic_m,options)); // frontAnim = new ObjectAnimator(); // frontAnim.setFloatValues(0,90f); // frontAnim.setDuration(1000); // frontAnim.setInterpolator(new LinearInterpolator()); // frontAnim.addListener(new Animator.AnimatorListener() { // @Override // public void onAnimationStart(Animator animation) { // // } // // @Override // public void onAnimationEnd(Animator animation) { // imageViews[index].setVisibility(View.INVISIBLE); // index = (index+1)%2; // imageViews[index].setVisibility(View.VISIBLE); // backAnim.start(); // } // // @Override // public void onAnimationCancel(Animator animation) { // // } // // @Override // public void onAnimationRepeat(Animator animation) { // // } // }); // ValueAnimator.AnimatorUpdateListener updateListener = new ValueAnimator.AnimatorUpdateListener() { // @Override // public void onAnimationUpdate(ValueAnimator animation) { // float value = (Float) animation.getAnimatedValue(); // imageViews[index].setRotationY(value); // } // }; // frontAnim.addUpdateListener(updateListener); // // backAnim = new ObjectAnimator(); // backAnim.setFloatValues(270f,360f); // backAnim.setDuration(1000); // backAnim.setInterpolator(new LinearInterpolator()); // backAnim.addListener(new Animator.AnimatorListener() { // @Override // public void onAnimationStart(Animator animation) { // } // // @Override // public void onAnimationEnd(Animator animation) { // isAnim = false; // } // // @Override // public void onAnimationCancel(Animator animation) { // } // // @Override // public void onAnimationRepeat(Animator animation) { // } // }); // backAnim.addUpdateListener(updateListener); } private boolean isAnim = false; public void startAnimation(View view){ if(isAnim){ return; } isAnim = true; if(frontAnim == null){ final float centerX = imageViews[0].getWidth() / 2.0f; final float centerY = imageViews[0].getHeight() / 2.0f; frontAnim= new Rotate3dAnimation(this,0, 90, centerX, centerY, 0f, true,0); frontAnim.setDuration(1000); //设置动画时长 frontAnim.setFillAfter(true); //保持旋转后效果 frontAnim.setInterpolator(new LinearInterpolator()); //设置插值器 backAnim = new Rotate3dAnimation(this,-90, 0, centerX, centerY, 0f, true,0); backAnim.setDuration(1000); backAnim.setFillAfter(true); backAnim.setInterpolator(new LinearInterpolator()); frontAnim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { imageViews[index].setVisibility(View.INVISIBLE); imageViews[index].clearAnimation(); index = (index+1)%2; imageViews[index].setVisibility(View.VISIBLE); imageViews[index].startAnimation(backAnim); } @Override public void onAnimationRepeat(Animation animation) { } }); backAnim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { isAnim = false; imageViews[index].clearAnimation(); } @Override public void onAnimationRepeat(Animation animation) { } }); } imageViews[index].startAnimation(frontAnim); // frontAnim.start(); } }

还是要好好研究研究android.graphics.Camera

 
转载请注明原文地址: https://www.6miu.com/read-5032623.html

最新回复(0)