溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android仿360市場下載按鈕的實(shí)現(xiàn)方法

發(fā)布時間:2020-08-25 03:38:35 來源:腳本之家 閱讀:165 作者:daisy 欄目:移動開發(fā)

首先來看看效果圖:

Android仿360市場下載按鈕的實(shí)現(xiàn)方法

無論多復(fù)雜的動畫我們都是可以分割成小單元的,然后分步來實(shí)現(xiàn)。這個動畫大概分為收縮,準(zhǔn)備,加載,完成幾個部分。為此定義一個枚舉類來描述view的狀態(tài)。

public enum Status { NORMAL, START, PRE, EXPAND, LOAD, END }

收縮動畫

使用動畫不斷改變圓角矩形的寬度,觸發(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)備動畫

此時旋轉(zhuǎn)動畫,是通過canvas繪制背景圓和三個小圓,然后不斷旋轉(zhuǎn)畫布來實(shí)現(xiàn)的,具體求圓心坐標(biāo)和角度動畫我們直接看代碼:

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();
 }

展開動畫

展開動畫也是不斷改變view的寬度并重繪圓角矩形,同時需要對準(zhǔn)備動畫的狀態(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();
 }

加載動畫

加載動畫分三部分,右側(cè)的旋轉(zhuǎn)動畫,正弦軌跡運(yùn)動的小球動畫,進(jìn)度更新的動畫。正弦動畫要求出正弦函數(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é)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI