1. 程式人生 > >一步一步實現高仿支付寶金額圓環圖

一步一步實現高仿支付寶金額圓環圖

現在應用裡面整合圖表是很常見的事了,簡單、直觀能給使用者更直觀的感受,包括支付寶,招商銀行App等,雖然有很多第三方的圖示庫,但是自己實現一個是不是很有成就感?主要優勢還是體現在自己可以實現一些特殊需求以及自己實現程式碼量小,不到150行。現在我們就來一步一步實現一個帶動畫的圓環圖,先放效果圖。


初始化一些值

privatestatic final String TAG = "RingView";

    private Paint mPaint;

    private Context mContext;

    //繪製區域寬

    private float mWidth;

    //繪製區域高

    private float mHeight;

    //外圓直徑

    private float mOuterRing;

    //顏色

    private int[] colors = newint[]{0xFFF9A947, 0xFFe57646, 0xFF1E71BC, 0xFF428BFE};

    //繪製區域正方形

    private RectF mRectF;

    //各繪製角度集合

    private List<Float> mListAcr;

    //內圈大小

    private float mInnerRing;

//繪製的進度

    private float mStartAcr = 1f;

    public RingView(Context context) {

        super(context, null, 0);

    }

    public RingView(Context context,AttributeSet attrs) {

        this(context, attrs, 0);

    }

    public RingView(Context context,AttributeSet attrs, int defStyleAttr) {

        super(context, attrs, defStyleAttr);

        mListAcr = new ArrayList<>();

        mContext = context;

        mPaint = new Paint();

        mPaint.setDither(true);

        mPaint.setAntiAlias(true);

        TypedArray typedArray =context.obtainStyledAttributes(attrs, R.styleable.RingView);

        mOuterRing =typedArray.getDimension(R.styleable.RingView_outer_ring_radius, 0);

        mInnerRing =typedArray.getDimension(R.styleable.RingView_inner_ring_radius, 0);

    }

    @Override

    protected void onMeasure(intwidthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec,heightMeasureSpec);

        mWidth = getMeasuredWidth();

        mHeight = getMeasuredHeight();

        float left = (mWidth - mOuterRing) / 2;

        float top = (mHeight - mOuterRing) / 2;

        mRectF = new RectF(left, top, mWidth -left, mHeight - top);

    }

佈局檔案:

<?xmlversion="1.0" encoding="utf-8"?>

<LinearLayout

   xmlns:android="http://schemas.android.com/apk/res/android"

   xmlns:app="http://schemas.android.com/apk/res-auto"

   android:layout_width="match_parent"

   android:layout_height="match_parent"

    android:gravity="center"

   android:orientation="vertical">

    <com.example.sheteng.ringview.RingView

        android:layout_width="90dp"

        android:id="@+id/ringview"

        android:layout_height="90dp"

        app:inner_ring_radius="30dp"

        app:outer_ring_radius="90dp"

       />

    <Button

       android:layout_marginTop="20dp"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

        android:onClick="showRing"

        android:text="點我"/>

</LinearLayout>


首先是計算部分,計算各個色塊佔據的角度,儲存到一個集合裡面

publicvoid initData(List<Float> list) {

        mListAcr.clear();

        if (list == null) {

            return;

        }

        float total = 0;

        for (Float integer : list) {

            total += integer;

        }

        if (total > 0) {

            float totalAcr = 0;

            for (int i = 0; i < list.size();i++) {

                float acr = (list.get(i) /total) * 360;

                if (i == list.size() - 1) {

                    acr = 360 - totalAcr;

                }

                totalAcr += acr;

                mListAcr.add(acr);

            }

        }

        invalidate();

    }

接下來考慮怎麼畫成圓餅,我這裡採用的是先畫成扇形,再在中間畫一個一個小白圓,疊加成為圓環,

@Override

    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        int total = 0;

        for (int i = 0; i < mListAcr.size();i++) {

            mPaint.setColor(colors[i]);

            if (mListAcr.get(i) == 0) {

                continue;

            }

            float endAcr = mListAcr.get(i);

            canvas.drawArc(mRectF, 270 + total,endAcr, true, mPaint);

               total += mListAcr.get(i);

        }

        mPaint.setColor(Color.WHITE);

        canvas.drawCircle(mWidth / 2, mHeight /2, mInnerRing / 2, mPaint);

    }

這樣的效果如下,是不是還差點什麼?


對,這不是沒動畫麼?動畫採用一次繪製比上一次繪製多幾個角度,一樣一次次繪製下來就形成了動畫。

@Override

    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        int total = 0;

        mStartAcr += 3;

        if (mStartAcr > 360) {

            mStartAcr = 360;

        }

        for (int i = 0; i < mListAcr.size();i++) {

            mPaint.setColor(colors[i]);

            if (mListAcr.get(i) == 0) {

                continue;

            }

            float endAcr = mStartAcr - total;

            if (endAcr > mListAcr.get(i)){

                endAcr = mListAcr.get(i);

            }

            canvas.drawArc(mRectF, 270 + total,endAcr, true, mPaint);

            if (mStartAcr >= total +mListAcr.get(i)) {

                total += mListAcr.get(i);

                continue;

            } else {

                break;

            }

        }

        mPaint.setColor(Color.WHITE);

        canvas.drawCircle(mWidth / 2, mHeight /2, mInnerRing / 2, mPaint);

        if (mStartAcr < 360) {

            invalidate();

        }

    }

mStartAcr記錄繪製的進度一次多繪製3個角度,效果如下:


有沒有覺得這動畫好生硬,我們每次都多畫3個角度當然生硬了,我們把3換成一個漸變值,讓他隨著繪製的進度調整值,先變大在變小,這裡我用的餘弦

@Override

    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        int total = 0;

        mStartAcr += getInterpolation(mStartAcr/ 360f);

        if (mStartAcr > 360) {

            mStartAcr = 360;

        }

        for (int i = 0; i < mListAcr.size();i++) {

            mPaint.setColor(colors[i]);

            if (mListAcr.get(i) == 0) {

                continue;

            }

            float endAcr = mStartAcr - total;

            if (endAcr > mListAcr.get(i)){

                endAcr = mListAcr.get(i);

            }

            canvas.drawArc(mRectF, 270 + total,endAcr, true, mPaint);

            if (mStartAcr >= total +mListAcr.get(i)) {

                total += mListAcr.get(i);

                continue;

            } else {

                break;

            }

        }

        mPaint.setColor(Color.WHITE);

        canvas.drawCircle(mWidth / 2, mHeight /2, mInnerRing / 2, mPaint);

        if (mStartAcr < 360) {

            invalidate();

        }

    }

    /**

     * 生成插值

     */

    public float getInterpolation(float input){

        double cos = Math.cos(input * Math.PI);

        return (float) ((1f - Math.abs(cos)) *6 + 3f);

    }

這樣就達到我們前面放的效果圖,大功告成了!

完整的專案地址:https://github.com/sheteng63/RingView

期待你們的star,如有問題,敬請指正!

相關推薦

實現仿支付金額

現在應用裡面整合圖表是很常見的事了,簡單、直觀能給使用者更直觀的感受,包括支付寶,招商銀行App等,雖然有很多第三方的圖示庫,但是自己實現一個是不是很有成就感?主要優勢還是體現在自己可以實現一些特殊需求以及自己實現程式碼量小,不到150行。現在我們就來一步一步實現一個帶動畫的圓環圖,先放效果圖。 初始化一

仿支付首頁

閒著沒事寫了一個支付寶首頁動畫的demo,有什麼問題,可以聯絡我 共同商量,感覺好記的給我點贊啊程式碼支援最低版本7.0OC程式碼下載地址:http://download.csdn.net/detail/u011604049/9882084Swift程式碼下載地址:http:

iOS仿支付賬單餅狀

前言: 這段時間專案做了一個賬單查詢的頁面使用到了餅狀圖,支付寶賬單那個餅狀圖,就簡單的封裝了一個給大家看看,使用的基本技術也就是使用UIBezierPath繪製柱狀圖路徑,再把CAShapeLayer和UIBezierPath建立關係,最後使用CABasicAnima

句程式碼叫你實現仿qq的側滑選單

           今天下午  小編在與同事們研究側滑選單的時候    百度搜索了很多例子    差不多都是一個人的專案   但是   使用起來  報錯  報錯  報錯      研究了好久   差點崩潰-------------於是我們打算自己研究    於是就這樣動了

趕緊查查你的微信和支付授權了多少應用!我竟然有100多個!

img sta 權限管理 com apt 多個 查詢 進入 pst 說起應用被授權,大家肯定都不陌生吧,因為現在很多軟件,小程序在使用的時候都需要通過微信或者QQ授權應用,其實支付寶也是哦,時間長了,授權應用就多了,我有100多個,查完嚇死了!你好奇你授權了多少個應用嗎?趕

卡拉OK歌詞原理和實現仿Android網易雲音樂

大家好,我們是愛學啊,繼上一篇講解了【LRC歌詞原理和實現高仿Android網易雲音樂】,今天給大家帶來一篇關於卡拉OK歌詞原理和在Android上如何實現歌詞逐字滾動的效果,本文來自【Android開發專案實戰我的雲音樂】課程。 效果圖 相信大家都懂一張圖勝過千言萬語。 效果和現在市面上大部分播放

LRC歌詞原理和實現仿Android網易雲音樂

大家好,我們是愛學啊,今天給大家帶來一篇關於LRC歌詞原理和在Android上如何實現歌詞逐行滾動的效果,本文來自【Android開發專案實戰我的雲音樂】課程;逐字滾動下一篇文章講解。 效果圖 相信大家都懂一張圖勝過千言萬語。 效果和現在市面上大部分播放器差不多,當然如果要運用到商業專案中,肯定還需

推薦一下github上鍵集合的微信和支付支付

1.微信支付 接入流程: 主要幾個步驟: 1.統一下單(放在服務端,需要加密引數) 2.生成支付引數(放在服務端,需要生成簽名) 3.呼叫客戶端SDK發起支付 4.服務端非同步接收支付結果 2.支付寶支付 接入流程: 生成支付引數(放在服務端,需要生成簽名) 呼叫客戶端

Android 實現仿iOS桌面效果之可拖動的GridView(上)

     最近專案中遇到一個LIstview的拖動效果,github上一搜發現有叫DragListview的開源專案,然後自己再小手一搜拖動排序的GridView,卻沒發現什麼很全很好的開源專案,後

Android 仿支付搜尋結果頁,字串部分文字顯示

最近收到一個需求就是,搜尋的關鍵詞,在搜尋結果頁的搜尋條目上高亮顯示。類似於支付寶搜尋結果頁的效果。 先來看一下效果如下圖: 經過一番思慮之後,感覺還是比較簡單的,直接上程式碼 /** * 字串高亮顯示部分文字 * @param textView

仿支付笑臉重新整理載入動畫的實現

看到支付寶的下拉重新整理有一個笑臉的動畫,因此自己也動手實現一下。效果圖如下: 一、總體思路 1、靜態部分的笑臉。 這一部分的笑臉就是一個半圓弧,加上兩顆眼睛,這部分比較簡單,用於一開始的展示。 2、動態笑臉的實現。 2.1、先是從底部

TextView實現仿京東活動倒計時

  電商活動是比較多的,所以活動倒計時功能是必不可少的,自己當初實現的時候是採用複合佈局,最近突然發現京東的竟然是用原生的ImageView實現的,666啊!於是就開始Google,終於找到了類似的實現方法,就是利用android的ImageSpan實現的

Android控制元件GridView之仿支付錢包首頁帶有分割線的GridView九宮格的完美實現

部落格時間:2015-02-04 15:03 今天我們來模仿一下支付寶錢包首頁中帶有分割線的GridView,俗稱九宮格。先上圖,是你想要的效果麼?如果是請繼續往下看。                                               

仿支付錢包首頁帶有分割線的GridView九宮格的完美實現

我們來模仿一下支付寶錢包首頁中帶有分割線的GridView,俗稱九宮格。先上圖,是你想要的效果麼?如果是請繼續往下看。 我們都知道ListView設定分割線是非常容易的,設定ListView的分割線顏色和寬度,只需要在佈局中定義android:divide

Swift3.0二維碼掃描實現(寫一個仿支付二維碼掃描的效果)

關鍵程式碼 import AVFoundation //獲取攝像裝置 let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) do { //建立輸入,輸出流

Vue2.0實現仿餓了麼專案裡的小球飛入動畫

在學習Vue.js高仿餓了麼專案的過程中,有一個小球飛入購物車的動畫效果。專案是基於vue1.0的,如果是vue2.0的專案,該如何實現呢?自己也花時間研究了一會,從迷惑不解,各種嘗試未果,到後來咬文嚼字研讀vue 2.0官網關於過渡的章節,再到最終實現效果,心情十分愉悅,同

淺談android中僅僅使用一個TextView實現仿京東,淘各種倒計時

  今天給大家帶來的是僅僅使用一個TextView實現一個高仿京東、淘寶、唯品會等各種電商APP的活動倒計時。最近公司一直加班也沒來得及時間去整理,今天難得休息想把這個分享給大家,只求共同學習,以及自己後續的複習。為什麼會想到使用一個TextView來實現呢?因為最近公司在

Android簡單實現仿支付新年紅包活動頁面的動態佈局效果

大家好,隔了很長一段時間沒有更新部落格了,有幾方面的原因,一是因為年底了在準備換工作的事情,二是因為年底了公司專案需要一個歸檔和總結的內容,所以做了一個月的開發共通元件的抽取成SDK的工作,內容都是一些平時比較常用的功能模組,比如像登入註冊,第三方註冊和分享

純JS、CSS3實現仿IOS訊息alert彈窗(警告框,確認框,提示框)。老鐵們,沒毛病。

簡潔,大方的ios彈窗風格。網上有很多關於alert 彈窗的栗子可以借鑑使用。本文章主要應用在移動端上面的彈窗實現。 在專案沒有應用到其他框架彈窗的基礎上, 此例項應該可以滿足大部分彈窗上的要求,可直接應用於專案之中。使用方法: 1、引入依賴的樣式檔案和指

文帶你瞭解微信/支付支付的相關概念

今天寫了一篇非技術文,需求來源於老大的老大,老老大。 這偏文章用以說明微信/支付寶相關引數之間錯綜複雜的關係,所有資料來自微信/支付寶官網,以及相關銀聯給的微信/支付寶對接文件。 嘿嘿,如果同行的小夥伴,也有這個疑惑,希望本篇文章幫你解惑。 ## 微信 名詞解釋: - **appid**:公眾號、小