Android仿360市場(chǎng)下載按鈕的實(shí)現(xiàn)方法
首先來看看效果圖:

無論多復(fù)雜的動(dòng)畫我們都是可以分割成小單元的,然后分步來實(shí)現(xiàn)。這個(gè)動(dòng)畫大概分為收縮,準(zhǔn)備,加載,完成幾個(gè)部分。為此定義一個(gè)枚舉類來描述view的狀態(tài)。
public enum Status { NORMAL, START, PRE, EXPAND, LOAD, END }
收縮動(dòng)畫
使用動(dòng)畫不斷改變圓角矩形的寬度,觸發(fā)重繪。代碼如下:
private void initAnim() {
Animation animation1 = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
mCurrLength = mWidth * (1 - interpolatedTime);
if (mCurrLength < mHeight) {
mCurrLength = mHeight;
clearAnimation();
mAngleAnim.start();
}
invalidate();
}
};
animation1.setDuration(mShrinkDuration);
animation1.setInterpolator(new LinearInterpolator());
animation1.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
mStatus = Status.START;
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mShrinkAnim = animation1;
...
}
onDraw中繪制:
if (mStatus == Status.START || mStatus == Status.NORMAL) {
float left = (mWidth - mCurrLength) / 2f;
float right = (mWidth + mCurrLength) / 2f;
float r = mHeight / 2f;
canvas.drawRoundRect(new RectF(left, 0, right, mHeight), r, r, mBgPaint);
if (mStatus == Status.NORMAL) {
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float y = mHeight / 2 + (fm.descent - fm.ascent) / 2 - fm.descent;
canvas.drawText("下載", mWidth / 2, y, mTextPaint);
}
}
準(zhǔn)備動(dòng)畫
此時(shí)旋轉(zhuǎn)動(dòng)畫,是通過canvas繪制背景圓和三個(gè)小圓,然后不斷旋轉(zhuǎn)畫布來實(shí)現(xiàn)的,具體求圓心坐標(biāo)和角度動(dòng)畫我們直接看代碼:
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAngle += mPreAnimSpeed;
invalidate();
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mStatus = Status.PRE;
}
@Override
public void onAnimationEnd(Animator animation) {
mAngleAnim.cancel();
startAnimation(mTranslateAnim);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.setDuration(mPreAnimDuration);
animator.setInterpolator(new LinearInterpolator());
mAngleAnim = animator;
onDraw中繪制代碼:
if (mStatus == Status.PRE) {
canvas.drawCircle(mWidth / 2f, mHeight / 2f, mHeight / 2f, mBgPaint);
canvas.save();
mTextPaint.setStyle(Paint.Style.FILL);
canvas.rotate(mAngle, mWidth / 2, mHeight / 2);
//大圓的圓心 半徑
float cX = mWidth / 2f;
float cY = mHeight / 2f;
float radius = mHeight / 2 / 3f;
canvas.drawCircle(cX, cY, radius, mTextPaint);
//上方小圓的參數(shù)
float rr = radius / 2f;
float cYY = mHeight / 2 - (radius + rr / 3);
canvas.drawCircle(cX, cYY, rr, mTextPaint);
//左下小圓參數(shù)
float cXX = (float) (cX - Math.sqrt(2) / 2f * (radius + rr / 3f));
cYY = (float) (mHeight / 2 + Math.sqrt(2) / 2f * (radius + rr / 3f));
canvas.drawCircle(cXX, cYY, rr, mTextPaint);
//右下小圓參數(shù)
cXX = (float) (cX + Math.sqrt(2) / 2f * (radius + rr / 3f));
canvas.drawCircle(cXX, cYY, rr, mTextPaint);
canvas.restore();
}
展開動(dòng)畫
展開動(dòng)畫也是不斷改變view的寬度并重繪圓角矩形,同時(shí)需要對(duì)準(zhǔn)備動(dòng)畫的狀態(tài)進(jìn)行向右位移。
Animation animator1 = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
mCurrLength = mHeight + (mWidth - mHeight) * interpolatedTime;
mTranslationX = (mWidth - mHeight) / 2 * interpolatedTime;
invalidate();
}
};
animator1.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
mStatus = Status.EXPAND;
}
@Override
public void onAnimationEnd(Animation animation) {
clearAnimation();
mLoadAngleAnim.start();
mMovePointAnim.start();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
animator1.setDuration(mExpandAnimDuration);
animator1.setInterpolator(new LinearInterpolator());
mTranslateAnim = animator1;
onDraw中繪制代碼
if (mStatus == Status.EXPAND) {
float left = (mWidth - mCurrLength) / 2f;
float right = (mWidth + mCurrLength) / 2f;
float r = mHeight / 2f;
canvas.drawRoundRect(new RectF(left, 0, right, mHeight), r, r, mBgPaint);
canvas.save();
mTextPaint.setStyle(Paint.Style.FILL);
canvas.translate(mTranslationX, 0);
//大圓的圓心 半徑
float cX = mWidth / 2f;
float cY = mHeight / 2f;
float radius = mHeight / 2 / 3f;
canvas.drawCircle(cX, cY, radius, mTextPaint);
//上方小圓的參數(shù)
float rr = radius / 2f;
float cYY = mHeight / 2 - (radius + rr / 3);
canvas.drawCircle(cX, cYY, rr, mTextPaint);
//左下小圓參數(shù)
float cXX = (float) (cX - Math.sqrt(2) / 2f * (radius + rr / 3f));
cYY = (float) (mHeight / 2 + Math.sqrt(2) / 2f * (radius + rr / 3f));
canvas.drawCircle(cXX, cYY, rr, mTextPaint);
//右下小圓參數(shù)
cXX = (float) (cX + Math.sqrt(2) / 2f * (radius + rr / 3f));
canvas.drawCircle(cXX, cYY, rr, mTextPaint);
canvas.restore();
}
加載動(dòng)畫
加載動(dòng)畫分三部分,右側(cè)的旋轉(zhuǎn)動(dòng)畫,正弦軌跡運(yùn)動(dòng)的小球動(dòng)畫,進(jìn)度更新的動(dòng)畫。正弦動(dòng)畫要求出正弦函數(shù)的周期,y軸偏移量,x軸偏移量。
ValueAnimator animator2 = ValueAnimator.ofFloat(0, 1);
animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mLoadAngle += mLoadRotateAnimSpeed;
invalidate();
}
});
animator2.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mStatus = Status.LOAD;
}
@Override
public void onAnimationEnd(Animator animation) {
mLoadAngleAnim.cancel();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator2.setDuration(Integer.MAX_VALUE);
animator2.setInterpolator(new LinearInterpolator());
mLoadAngleAnim = animator2;
onDraw中繪制代碼:
if (mStatus == Status.LOAD || mStatus == Status.END) {
float left = (mWidth - mCurrLength) / 2f;
float right = (mWidth + mCurrLength) / 2f;
float r = mHeight / 2f;
mBgPaint.setColor(mProgressColor);
canvas.drawRoundRect(new RectF(left, 0, right, mHeight), r, r, mBgPaint);
if (mProgress != 100) {
for (int i = 0; i < mFourMovePoints.length; i++) {
if (mFourMovePoints[i].isDraw)
canvas.drawCircle(mFourMovePoints[i].moveX, mFourMovePoints[i].moveY, mFourMovePoints[i].radius, mTextPaint);
}
}
float progressRight = mProgress * mWidth / 100f;
mBgPaint.setColor(mBgColor);
canvas.save();
canvas.clipRect(0, 0, progressRight, mHeight);
canvas.drawRoundRect(new RectF(left, 0, right, mHeight), r, r, mBgPaint);
canvas.restore();
if (mProgress != 100) {
canvas.drawCircle(mWidth - mHeight / 2, mHeight / 2, mHeight / 2, mBgPaint);
canvas.save();
mTextPaint.setStyle(Paint.Style.FILL);
canvas.rotate(mLoadAngle, mWidth - mHeight / 2, mHeight / 2);
canvas.drawCircle(mWidth - mHeight + 30, getCenterY(mWidth - mHeight + 30, 5), 5, mTextPaint);
canvas.drawCircle(mWidth - mHeight + 45, getCenterY(mWidth - mHeight + 45, 8), 8, mTextPaint);
canvas.drawCircle(mWidth - mHeight + 68, getCenterY(mWidth - mHeight + 68, 11), 11, mTextPaint);
canvas.drawCircle(mWidth - mHeight + 98, getCenterY(mWidth - mHeight + 98, 14), 14, mTextPaint);
canvas.restore();
}
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float y = mHeight / 2 + (fm.descent - fm.ascent) / 2 - fm.descent;
canvas.drawText(mProgress + "%", mWidth / 2, y, mTextPaint);
}
項(xiàng)目主頁:http://www.open-open.com/lib/view/home/1494985743108
本地下載:http://xiazai.jb51.net/201705/yuanma/Metal626-360DownLoadView(jb51.net).rar
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- Android按鈕按下的時(shí)候改變顏色實(shí)現(xiàn)方法
- Android編程實(shí)現(xiàn)設(shè)置按鈕背景透明與半透明及圖片背景透明的方法
- 如何在Android中實(shí)現(xiàn)漸顯按鈕的左右滑動(dòng)效果
- Android實(shí)現(xiàn)圓角Button按鈕
- Android單選按鈕對(duì)話框用法實(shí)例分析
- Android動(dòng)畫 實(shí)現(xiàn)開關(guān)按鈕動(dòng)畫(屬性動(dòng)畫之平移動(dòng)畫)實(shí)例代碼
- Android自定義實(shí)現(xiàn)開關(guān)按鈕代碼
- Android利用懸浮按鈕實(shí)現(xiàn)翻頁效果
- Android學(xué)習(xí)系列一用按鈕實(shí)現(xiàn)顯示時(shí)間
- 安卓(android)仿電商app商品詳情頁按鈕浮動(dòng)效果
相關(guān)文章
Android ContentProvider獲取手機(jī)聯(lián)系人實(shí)例
這篇文章主要介紹了Android ContentProvider獲取手機(jī)聯(lián)系人實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Android自動(dòng)測(cè)試工具M(jìn)onkey的實(shí)現(xiàn)方法
本文主要介紹Android Monkey 實(shí)現(xiàn)方法,Monkey測(cè)試是一種為了測(cè)試軟件的穩(wěn)定性、健壯性的快速有效的方法,具有非常重要的參考價(jià)值,希望對(duì)小伙伴有所幫助2016-07-07
Android實(shí)現(xiàn)沉浸式通知欄通知欄背景顏色跟隨app導(dǎo)航欄背景顏色而改變
這篇文章主要介紹了Android實(shí)現(xiàn)沉浸式通知欄通知欄背景顏色跟隨app導(dǎo)航欄背景顏色而改變的相關(guān)資料,需要的朋友可以參考下2016-02-02
Android仿淘寶view滑動(dòng)至屏幕頂部會(huì)一直停留在頂部的位置
這篇文章主要介紹了Android仿淘寶view滑動(dòng)至屏幕頂部會(huì)一直停留在頂部的位置的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11
Android 自定義view之畫圖板實(shí)現(xiàn)方法
本文重在對(duì)自定義view,以及其常用類,常用方法的初步了解,提供一個(gè)思路,效果是其次,畫板只是例子,需要的朋友可以參考下2018-01-01

