帶顏色漸變效果的的矩形進度條

先看一下效果:


有沒有亮瞎你的眼?

嗯...我說結尾的顏色。


先分析下實現的邏輯:我們用一個Drawable對象設置爲button的背景;→Drawable對象我們取它的子類BitmapDrawable的一個實例,BitmapDrawAble需要一個Bitmap對象;→繪製這個bitmap:有一個外邊的框框我們畫一個矩形,進度那條線我們使用繪製一個Path來表現;→當前的進度值乘以矩形的周長是path的長度,根據這個長度和矩形周長的關係,使用path的lineTo,moveTo等函數對其進行設置,然後繪製這個path。→顏色根據進度值改變得到一個變化的顏色。


實現細節:

1,得到矩形寬高:在onclick事件中

        w = v.getMeasuredWidth();
        h = v.getMeasuredHeight();
2,根據進度得到Path,這裏我是以頂部的中點爲起點順時針計算進度的,這裏可以隨意發揮,周長乘以這個進度得到path的長度,在按照你設計好的起點和方向畫線,遇到頂點時判斷path需不需要拐彎。

 /**
     * 根據百分比得到路徑
     *
     * @param pro 0~1之間的一個浮點數
     * @return
     */
    public Path getPath(float pro) {
        pro = pro * (w * 2 + h * 2);
        Path p = new Path();
        p.moveTo(w / 2, 0);
        if (pro < w / 2) {
            p.lineTo(w / 2 + pro, 0);
            return p;
        } else {
            p.lineTo(w, 0);
        }
        if (pro < w / 2 + h) {
            p.lineTo(w, (pro - w / 2));
            return p;
        } else {
            p.lineTo(w, h);
        }
        if (pro < w / 2 + h + w) {
            p.lineTo((w - (pro - h - w / 2)), h);
            return p;
        } else {
            p.lineTo(0, h);
        }
        if (pro < w / 2 + h + h + w) {
            p.lineTo(0, h - (pro - w - h - w / 2));
            return p;
        } else {
            p.lineTo(0, 0);
        }
        p.lineTo(pro - w - h * 2 - w / 2, 0);
        return p;
    }

3,根據進度得到一個漸變色,漸變色的原理沒有搜到,這裏模擬了一下,RGB顏色讓其中一個或幾個通道的顏色值在一定範圍內漸變。

   /**
     * 得到顏色梯度中間值 這裏可以自己定義
     *
     * @param pro 0~1之間的一個浮點數
     * @return
     */
    public int getColor(float pro) {
        int c = Color.argb(255, 100+(int) ((1 - pro) * 130), (int) (pro * 255), 155);
        return c;
    }

4,得到背景Drawable對象,這裏沒什麼好說的,畫筆設置之前根據進度值得到的顏色,設置不同寬度分別畫path和矩形。

 /**
     * 得到DrawAble對象
     *
     * @param path
     * @param color
     * @return
     */
    public Drawable getBgDrawAble(Path path, int color) {
        Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(b);
        Paint paint = new Paint();
        paint.setColor(color);
        paint.setStrokeWidth(30);
        paint.setStyle(Paint.Style.STROKE);
        c.drawPath(path, paint);
        paint.setStrokeWidth(3);
        c.drawRect(0,0,w,h,paint);
        BitmapDrawable bd = new BitmapDrawable(b);
        return bd;
    }
5,這裏模擬一個下載的使用場景:

在onclick事件中開啓一個異步任務:

 public void download(View v) {
        w = v.getMeasuredWidth();
        h = v.getMeasuredHeight();
        new DownloadTask(v).execute();
    }

 class DownloadTask extends AsyncTask<Void, Float, Boolean> {
        View v;

        public DownloadTask(View v) {
            this.v = v;
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            for (int i = 0; i <= 200; i++) {
                publishProgress(i * 1.0f / 200);
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return true;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            ((Button)v).setClickable(false);// 設置按鈕不可點擊
        }

        @Override
        protected void onPostExecute(Boolean integer) {
            super.onPostExecute(integer);
            ((Button)v).setText("下載完成");
            ((Button)v).setClickable(true);
        }

        @Override
        protected void onProgressUpdate(Float... values) {
            float rate = values[0];
            int col = getColor(rate);
            ((Button)v).setTextColor(col);
            v.setBackground(getBgDrawAble(getPath(rate), col));
            ((Button)v).setText("已下載" + (rate < 0.1 ? "0" : "") + (int)(rate*100) + "%");//計算下載進度並設置文字
            super.onProgressUpdate(values);
        }
    }

這個估計是最土的實現方法了,效率神馬的待我腦補相關知識再考慮吧。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章