本篇内容主要讲解“Android怎么实现加载视差动画效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android怎么实现加载视差动画效果”吧!
基础知识
继 Android实现旋转动画的两种方式 我们了解了 Android实现旋转的两种基本方法之后,我们来写一个综合案例
效果展示
代码实现
实现思路
从效果中我们可以看到 可以将其分为三个动画:
旋转动画(Android实现旋转动画的两种方式)
聚合动画
扩展动画
代码展示
package com.wust.mydialog; import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;import android.view.WindowManager;import android.view.animation.AnticipateInterpolator;import android.view.animation.LinearInterpolator; import androidx.annotation.Nullable; public class MyRotateView extends View { //设置旋转间隔时间 private int SPLASH_CIRCLE_ROTATE_TIME = 1000; //设置中心圆半径 private float CENTER_CIRCLE_RADIUS; private float SMALL_CIRCLE_RADIUS; private float mCurrentSingle = 0f; private int[] mColorArray; private Paint mCirclePaint; private ValueAnimator va; private Matrix mSpaceMatrix; private LoadingState mLoadingState; //当前中心圆半径 private float mCurCenterRadius; private float mDiagonal; private float mLineWidth; public MyRotateView(Context context) { super(context); } public MyRotateView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public MyRotateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); //初始化参数 initParams(width, height); setMeasuredDimension(width, height); } private void initParams(int w, int h) { //设置中心圆半径 CENTER_CIRCLE_RADIUS = 1 / 4.0f * w; //设置小圆的半径 SMALL_CIRCLE_RADIUS = 1 / 25.0f * w; //获取小球颜色 mColorArray = getResources().getIntArray(R.array.splash_circle_colors); //初始化画笔 mCirclePaint = new Paint(); mCirclePaint.setDither(true); mCirclePaint.setAntiAlias(true); //初始化旋转矩阵 mSpaceMatrix = new Matrix(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mLoadingState == null) { mLoadingState = new RotateState(); } mLoadingState.onDraw(canvas); } //定义 状态 抽象类 private abstract class LoadingState { public abstract void onDraw(Canvas canvas); } //旋转动画 private class RotateState extends LoadingState { public RotateState() { //计算每个小球的间隔 double spaceAngle = 360.0d / mColorArray.length; //初始化旋转矩阵 mSpaceMatrix.reset(); mSpaceMatrix.postRotate((float) spaceAngle, getWidth() / 2, getHeight() / 2); va = ObjectAnimator.ofFloat(0f, 360.0f); va.setDuration(SPLASH_CIRCLE_ROTATE_TIME); va.setRepeatCount(ValueAnimator.INFINITE); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mCurrentSingle = (float) animation.getAnimatedValue(); invalidate(); } }); va.setInterpolator(new LinearInterpolator()); va.start(); } @Override public void onDraw(Canvas canvas) { //绘制背景 canvas.drawColor(Color.WHITE); //利用旋转画布法 canvas.save(); canvas.rotate(mCurrentSingle, getWidth() / 2, getHeight() / 2); for (int i = 0; i < mColorArray.length; i++) { canvas.concat(mSpaceMatrix); //为 每个球 画笔 设置颜色 mCirclePaint.setColor(mColorArray[i]); //利用旋转画布法 float cx = getWidth() / 2 + CENTER_CIRCLE_RADIUS; float cy = getHeight() / 2; canvas.drawCircle(cx, cy, SMALL_CIRCLE_RADIUS, mCirclePaint); } canvas.restore(); } } //聚合动画 private class ScaleState extends LoadingState { public ScaleState() { va = ObjectAnimator.ofFloat(CENTER_CIRCLE_RADIUS,0); va.setDuration(SPLASH_CIRCLE_ROTATE_TIME); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mCurCenterRadius = (float) animation.getAnimatedValue(); invalidate(); } }); va.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mLoadingState = new ExtentState(); } }); va.setInterpolator(new AnticipateInterpolator()); va.start(); } @Override public void onDraw(Canvas canvas) { //绘制背景 canvas.drawColor(Color.WHITE); //绘制小圆 canvas.save(); //这句话也不能调,要不然不连贯 canvas.rotate(mCurrentSingle,getWidth()/2,getHeight()/2); for (int i = 0; i < mColorArray.length; i++) { mCirclePaint.setColor(mColorArray[i]); canvas.concat(mSpaceMatrix); canvas.drawCircle(mCurCenterRadius+getWidth()/2,getHeight()/2,SMALL_CIRCLE_RADIUS,mCirclePaint); } canvas.restore(); } } //扩展动画 public class ExtentState extends LoadingState{ public ExtentState() { //初始化对角线 float cx = getWidth()/2.0f; float cy = getHeight()/2.0f; mDiagonal = (float) Math.sqrt(Math.pow(cx,2)+Math.pow(cy,2)); va = ObjectAnimator.ofFloat(mDiagonal,0); va.setDuration(3000); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mLineWidth = (float) animation.getAnimatedValue(); invalidate(); } }); va.setInterpolator(new LinearInterpolator()); va.start(); } @Override public void onDraw(Canvas canvas) { mCirclePaint.setColor(Color.WHITE); mCirclePaint.setStrokeWidth(mLineWidth*2);//元的半径只会到达线宽的中间,所以要乘2 mCirclePaint.setStyle(Paint.Style.STROKE); canvas.drawCircle(getWidth()/2,getHeight()/2,mDiagonal,mCirclePaint); } } public void dismiss() { if (mLoadingState instanceof RotateState){ //取消旋转值动画 va.cancel(); //创建缩放动画 mLoadingState = new ScaleState(); //刷新布局、可以写也可以不写// invalidate(); } }}
到此,相信大家对“Android怎么实现加载视差动画效果”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!