Android使用Path仿支付寶支付成功失敗動畫

序言:最近空閒的時候一直在學習自定義View的相關知識,這也是LZ最近半年的學習對象,有的時候就是要給本身定下一個小目標,我們沒有王老闆的先賺他一個億這麼豪氣,也得先有個目標不是。逛博客的時候看到支付寶支付成功失敗的動畫效果,恰好最近在學習Path的相關知識,就想着實踐一下,也鞏固一下本身所學的知識,話很少說直接上圖。

這個也是公司項目中須要的,以前因爲項目緊,直接讓UI切了個圖,就這樣上了,這不太符合個人一向做風,可是沒辦法>_<

首先咱們來分解一下這個動做,首先是一段progressDialog,能夠看作是在請求數據等待過程,而後成功以後顯示成功的動畫,失敗以後顯示失敗的動畫,那麼這裏涉及到三個狀態,加載中、加載成功和加載失敗,這裏咱們使用枚舉來實現這三種狀態。首先呢,咱們先來實現這個等待的進度條:

一、畫一個圓,確切的來講是畫一段圓弧,而後旋轉畫布,在此過程當中不斷修改圓弧的大小,形成一個這樣動態的假象:git

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.translate(getPaddingLeft(), getPaddingTop());   //將當前畫布的點移到getPaddingLeft,getPaddingTop,後面的操做都以該點做爲參照點
    if (mStatus == StatusEnum.Loading) {    //正在加載
        if (startAngle == minAngle) {
            sweepAngle += 6;
        }
        if (sweepAngle >= 300 || startAngle > minAngle) {
            startAngle += 6;
            if (sweepAngle > 20) {
                sweepAngle -= 6;
            }
        }
        if (startAngle > minAngle + 300) {
            startAngle %= 360;
            minAngle = startAngle;
            sweepAngle = 20;
        }
        canvas.rotate(curAngle += 4, progressRadius, progressRadius);  //旋轉的弧長爲4
        canvas.drawArc(new RectF(0, 0, progressRadius * 2, progressRadius * 2), startAngle, sweepAngle, false, mPaint);
        invalidate();
    }
}複製代碼

這裏startAngle表示圓弧的起始角度,sweepAngle表示圓弧掃過的角度,minAngle是一個過渡值,是爲了幫助startAngle改變值而用到的。這裏用到了畫弧度的方法,在上一篇博客中我有細講這個方法,若是你還不知道的話請移步Android自定義view之圓形進度條,這裏還用到了rotate方法,來看一下它的源碼解釋:github

/**
 * Preconcat the current matrix with the specified rotation.
 *
 * @param degrees The amount to rotate, in degrees
 * @param px The x-coord for the pivot point (unchanged by the rotation)
 * @param py The y-coord for the pivot point (unchanged by the rotation)
 */
public final void rotate(float degrees, float px, float py) {
    translate(px, py);
    rotate(degrees);
    translate(-px, -py);
}複製代碼

這個方法主要是將畫布進行旋轉,咱們能夠看到,先是將畫布平移到某個點,而後再旋轉某個角度,最後再平移回去,這樣作的目的是爲了讓須要旋轉的View進行中心對稱旋轉,因此後面傳的PX,PY值須要是View寬高的一半,不信的話你能夠去作個實驗;說了這麼多咱們直接來看一下效果:canvas

二、畫成功狀態的動畫,這部分也能夠分紅兩個小部分,先是畫一個圓,而後再畫中間的鉤:
(1)、畫圓:上一篇博客中講了經過進度來畫弧進而來畫整個圓,今天咱們的主角是Path,因此咱們使用Path來實現這樣一個效果,仍是先上代碼,經過代碼來說解:bash

//追蹤Path的座標
private PathMeasure mPathMeasure;
//畫圓的Path
private Path mPathCircle;
//截取PathMeasure中的path
private Path mPathCircleDst;

mPaint.setColor(loadSuccessColor);
mPathCircle.addCircle(getWidth() / 2, getWidth() / 2, progressRadius, Path.Direction.CW);
mPathMeasure.setPath(mPathCircle, false);
mPathMeasure.getSegment(0, circleValue * mPathMeasure.getLength(), mPathCircleDst, true);
canvas.drawPath(mPathCircleDst, mPaint);複製代碼

Path的經常使用方法有,add一條路徑(任意形狀,任意線條),這裏咱們在path中添加了一個圓的路徑,具體Path常見的用法以下表所示:eclipse

Path的常見方法 方法含義
moveTo() 該方法移動後續操做的起點座標
lineTo() 該方法是鏈接起始點與某一點(傳的參數)造成一條線
setLastPath() 該方法是設置Path最後的座標
close() 該方法是將起點座標與終點座標鏈接起來造成一個閉合的圖形(若是始終點左邊能鏈接的話)
addRect() 該方法是繪製一個巨型
addRoundRect() 該方法是繪製一個圓角矩形
addOval() 該方法是繪製一個橢圓
arcTo() 該方法是繪製一段圓弧
addArc() 該方法是繪製一段圓弧

而後呢,這裏有一個PathMeasure,簡單點說,這玩意就是用來實現Path座標點的追蹤,你也能夠認爲是Path座標的計算器,具體PathMeasure的常見的用法以下表所示:ide

PathMeasure的常見方法 方法含義
setPath() 該方法將path與PathMeasure綁定起來
getLength() 該方法用於得到path路徑的長度
getSegment() 該方法用於截取整個Path的片斷
nextContour() 該方法用於切換到下一個路徑

這裏咱們經過動畫從0——1之間的變化,來改變所畫圓的弧度:學習

circleAnimator = ValueAnimator.ofFloat(0, 1);
circleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        circleValue = (float) animation.getAnimatedValue();
        invalidate();
    }
});複製代碼

(2)、接下來畫完圓以後,咱們要開始畫對鉤了:動畫

對鉤
對鉤

if (circleValue == 1) {      //表示圓畫完了,能夠鉤了
    successPath.moveTo(getWidth() / 1 * 3, getWidth() / 2);
    successPath.lineTo(getWidth() / 2, getWidth() / 5 * 3);
    successPath.lineTo(getWidth() / 3 * 2, getWidth() / 5 * 2);
    mPathMeasure.nextContour();
    mPathMeasure.setPath(successPath, false);
    mPathMeasure.getSegment(0, successValue * mPathMeasure.getLength(), mPathCircleDst, true);
    canvas.drawPath(mPathCircleDst, mPaint);
}複製代碼

這裏的座標我是根據UI給的圖大體算出來的,能夠參考下面這張圖的虛線和實現,對鉤的起始座標在座標軸中大體是getWidth() / 8 * 3,你也能夠根據你的需求來畫出這個對鉤,其實就是兩段路徑,分別用pathlineTo方法來實現:ui

成功畫對勾
成功畫對勾

同理,畫叉叉也是同樣的,只要你算出叉在座標軸中的座標就ok了,這裏我也給出一張參考圖:spa

叉叉
叉叉

mPaint.setColor(loadFailureColor);
mPathCircle.addCircle(getWidth() / 2, getWidth() / 2, progressRadius, Path.Direction.CW);
mPathMeasure.setPath(mPathCircle, false);
mPathMeasure.getSegment(0, circleValue * mPathMeasure.getLength(), mPathCircleDst, true);
canvas.drawPath(mPathCircleDst, mPaint);

if (circleValue == 1) {  //表示圓畫完了,能夠畫叉叉的右邊部分
    failurePathRight.moveTo(getWidth() / 3 * 2, getWidth() / 3);
    failurePathRight.lineTo(getWidth() / 3, getWidth() / 3 * 2);
    mPathMeasure.nextContour();
    mPathMeasure.setPath(failurePathRight, false);
    mPathMeasure.getSegment(0, failValueRight * mPathMeasure.getLength(), mPathCircleDst, true);
    canvas.drawPath(mPathCircleDst, mPaint);
}

if (failValueRight == 1) {    //表示叉叉的右邊部分畫完了,能夠畫叉叉的左邊部分
    failurePathLeft.moveTo(getWidth() / 3, getWidth() / 3);
    failurePathLeft.lineTo(getWidth() / 3 * 2, getWidth() / 3 * 2);
    mPathMeasure.nextContour();
    mPathMeasure.setPath(failurePathLeft, false);
    mPathMeasure.getSegment(0, failValueLeft * mPathMeasure.getLength(), mPathCircleDst, true);
    canvas.drawPath(mPathCircleDst, mPaint);
}複製代碼

失敗畫叉叉
失敗畫叉叉

參考:

Android自定義之仿支付寶支付成功、失敗狀態的加載進度

自定義View(三)使用Path仿支付寶支付成功效果

PathMeasure之迷徑追蹤

到此就完成了自定義的原型進度條了。源碼已上傳至Github,有須要的同窗能夠下載下來看看,歡迎Star,Fork

同時感謝以上引用到博客的主人,感謝!!!

公衆號:Android技術經驗分享
公衆號:Android技術經驗分享
相關文章
相關標籤/搜索