Android實現(xiàn)雅虎新聞?wù)虞d視差動畫效果
基礎(chǔ)知識
繼 Android實現(xiàn)旋轉(zhuǎn)動畫的兩種方式 我們了解了 Android實現(xiàn)旋轉(zhuǎn)的兩種基本方法之后,我們來寫一個綜合案例
效果展示

代碼實現(xiàn)
實現(xiàn)思路
從效果中我們可以看到 可以將其分為三個動畫:
1、旋轉(zhuǎn)動畫(Android實現(xiàn)旋轉(zhuǎn)動畫的兩種方式)
2、聚合動畫
3、擴(kuò)展動畫
代碼展示
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
* @技術(shù)交流QQ群 928023749
*/
public class MyRotateView extends View {
//設(shè)置旋轉(zhuǎn)間隔時間
private int SPLASH_CIRCLE_ROTATE_TIME = 1000;
//設(shè)置中心圓半徑
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;
//當(dāng)前中心圓半徑
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);
//初始化參數(shù)
initParams(width, height);
setMeasuredDimension(width, height);
}
private void initParams(int w, int h) {
//設(shè)置中心圓半徑
CENTER_CIRCLE_RADIUS = 1 / 4.0f * w;
//設(shè)置小圓的半徑
SMALL_CIRCLE_RADIUS = 1 / 25.0f * w;
//獲取小球顏色
mColorArray = getResources().getIntArray(R.array.splash_circle_colors);
//初始化畫筆
mCirclePaint = new Paint();
mCirclePaint.setDither(true);
mCirclePaint.setAntiAlias(true);
//初始化旋轉(zhuǎn)矩陣
mSpaceMatrix = new Matrix();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mLoadingState == null) {
mLoadingState = new RotateState();
}
mLoadingState.onDraw(canvas);
}
//定義 狀態(tài) 抽象類
private abstract class LoadingState {
public abstract void onDraw(Canvas canvas);
}
//旋轉(zhuǎn)動畫
private class RotateState extends LoadingState {
public RotateState() {
//計算每個小球的間隔
double spaceAngle = 360.0d / mColorArray.length;
//初始化旋轉(zhuǎn)矩陣
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);
//利用旋轉(zhuǎn)畫布法
canvas.save();
canvas.rotate(mCurrentSingle, getWidth() / 2, getHeight() / 2);
for (int i = 0; i < mColorArray.length; i++) {
canvas.concat(mSpaceMatrix);
//為 每個球 畫筆 設(shè)置顏色
mCirclePaint.setColor(mColorArray[i]);
//利用旋轉(zhuǎn)畫布法
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();
//這句話也不能調(diào),要不然不連貫
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();
}
}
//擴(kuò)展動畫
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);//元的半徑只會到達(dá)線寬的中間,所以要乘2
mCirclePaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(getWidth()/2,getHeight()/2,mDiagonal,mCirclePaint);
}
}
public void dismiss() {
if (mLoadingState instanceof RotateState){
//取消旋轉(zhuǎn)值動畫
va.cancel();
//創(chuàng)建縮放動畫
mLoadingState = new ScaleState();
//刷新布局、可以寫也可以不寫
// invalidate();
}
}
}
到此這篇關(guān)于Android實現(xiàn)雅虎新聞?wù)虞d視差動畫效果的文章就介紹到這了,更多相關(guān)android視覺動畫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
android:TextView簡單設(shè)置文本樣式和超鏈接的方法
這篇文章主要介紹了android:TextView簡單設(shè)置文本樣式和超鏈接的方法,涉及TextView常見文字屬性的相關(guān)操作技巧,需要的朋友可以參考下2016-08-08
橫豎屏切換導(dǎo)致頁面頻繁重啟screenLayout解析
這篇文章主要為大家介紹了橫豎屏切換導(dǎo)致頁面頻繁重啟screenLayout解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android短信備份及數(shù)據(jù)插入實現(xiàn)代碼解析
這篇文章主要介紹了Android短信備份及數(shù)據(jù)插入實現(xiàn)代碼解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11
Android開發(fā)之開發(fā)者頭條(一)啟動頁實現(xiàn)
這篇文章主要介紹了Android開發(fā)之開發(fā)者頭條(一)啟動頁實現(xiàn)的相關(guān)資料,需要的朋友可以參考下2016-04-04
Android開發(fā)中TextView文本過長滾動顯示實現(xiàn)方法分析
這篇文章主要介紹了Android開發(fā)中TextView文本過長滾動顯示實現(xiàn)方法,結(jié)合實例形式分析了Android項目開發(fā)中TextView顯示超長文本的具體操作技巧與注意事項,需要的朋友可以參考下2018-02-02
Android12四大組件之Activity生命周期變化詳解
雖然說我們天天都在使用Activity,但是你真的對Activity的生命機(jī)制完全了解了嗎?Activity的生命周期方法只有七個,但是其實那只是默認(rèn)的情況。也就是說在其他情況下,Activity的生命周期可能不會是按照我們以前所知道的流程,本章著重講解Activity的生命周期變化2022-07-07
Android App開發(fā)中ViewPager組件的入門使用教程
這篇文章主要介紹了Android App開發(fā)中ViewPager組件的入門使用教程,ViewPager主要用來實現(xiàn)通過滑動來切換頁面的效果,需要的朋友可以參考下2016-03-03
Android開發(fā)實現(xiàn)的Intent跳轉(zhuǎn)工具類實例
這篇文章主要介紹了Android開發(fā)實現(xiàn)的Intent跳轉(zhuǎn)工具類,簡單描述了Intent組件的功能并結(jié)合實例形式給出了頁面跳轉(zhuǎn)、拍照、圖片調(diào)用等相關(guān)操作技巧,需要的朋友可以參考下2017-11-11

