Android實現雅虎新聞摘要加載視差動畫效果
基礎知識
繼 Android實現旋轉動畫的兩種方式 我們瞭解瞭 Android實現旋轉的兩種基本方法之後,我們來寫一個綜合案例
效果展示
代碼實現
實現思路
從效果中我們可以看到 可以將其分為三個動畫:
1、旋轉動畫(Android實現旋轉動畫的兩種方式)
2、聚合動畫
3、擴展動畫
代碼展示
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; /** * ClassName: com.wust.mydialog.MyRotateView <br/> * Description: <br/> * date: 2021/8/7 12:13<br/> * * @author yiqi<br /> * @QQ 1820762465 * @微信 yiqiideallife * @技術交流QQ群 928023749 */ 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實現雅虎新聞摘要加載視差動畫效果的文章就介紹到這瞭,更多相關android視覺動畫內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Android實現旋轉動畫的兩種方式案例詳解
- Android模擬實現華為系統升級進度條
- Android使用貝塞爾曲線畫心形
- 詳解Android如何自定義view實現圓形進度條
- Android自定義view實現圓形進度條效果