自定義View——成長(zhǎng)值、積分進(jìn)度條

產(chǎn)品需求中難免有一些不符合常理的設(shè)計(jì)7不小V就骸!今天來設(shè)計(jì)針對(duì)一個(gè)會(huì)員嚼酝,積分系統(tǒng)浮还,設(shè)計(jì)一個(gè)水平的進(jìn)度條,首先看圖說話
image

看出圖中會(huì)員等級(jí)分為4級(jí)闽巩,每一級(jí)的長(zhǎng)度均分4個(gè)實(shí)心的點(diǎn)钧舌,分為四個(gè)區(qū)間,每個(gè)區(qū)間中設(shè)置均分的進(jìn)度涎跨,所以用普通的ProgressBar洼冻、SeekBar是無法實(shí)現(xiàn)的,所以必須自定義View隅很,使用畫筆畫撞牢。

1、畫線

我的思路就是先畫一條灰色的虛線叔营,讓后屋彪,畫四個(gè)點(diǎn),根據(jù)傳入的當(dāng)前的成長(zhǎng)值绒尊,計(jì)算出在哪個(gè)區(qū)間畜挥,進(jìn)而繪畫出紅色的線,并且設(shè)置實(shí)心的紅點(diǎn)的點(diǎn)

package com.wj.progressbardemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * 成長(zhǎng)值進(jìn)度條
 */

public class GrowthValueProgress extends View {

    private MyCallback callback;

    private Context context;

    private int currentValues = 1100;//當(dāng)前成長(zhǎng)值

    private int v0Values = 0;//v0會(huì)員成長(zhǎng)值

    private int v1Values = 100;//v1會(huì)員成長(zhǎng)值

    private int v2Values = 10000;//v2會(huì)員成長(zhǎng)值

    private int v3Values = 40000;//v3會(huì)員成長(zhǎng)值

    private int v4Values = 80000;//v4會(huì)員成長(zhǎng)值

    private Paint paint;//會(huì)員畫筆

    private Paint grayPaint;

    private Paint pointPaint1;

    private Paint pointPaint2;

    private Paint pointPaint3;

    private Paint pointPaint4;

    private int lineHeight = 8;//線的高度

    private int pointSize = 8;//圓心的半徑

    private int offsetX = 0;//x的坐標(biāo);

    private int width;

    private int hight;

    private List<Paint> paintList;

    public GrowthValueProgress(Context context) {
        super(context);
        this.context = context;
        initPaint();
    }

    public GrowthValueProgress(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        initPaint();
    }

    public GrowthValueProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        initPaint();
    }

    public int getCurrentValues() {
        return currentValues;
    }

    public void setCurrentValues(int currentValues) {
        this.currentValues = currentValues;
    }

    private void initPaint() {

        lineHeight=hight/2;//線的高度設(shè)置為布局的一半高度
        pointSize=hight/2;//圓點(diǎn)的半徑設(shè)置為布局的一半高度

        grayPaint = new Paint();
        grayPaint.setColor(Color.GRAY);
        grayPaint.setStrokeWidth(lineHeight);
        grayPaint.setAntiAlias(true);
        grayPaint.setTextAlign(Paint.Align.CENTER);
        grayPaint.setStyle(Paint.Style.STROKE);

        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(lineHeight);
        paint.setAntiAlias(true);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setStyle(Paint.Style.STROKE);


        pointPaint1 = new Paint();
        pointPaint2 = new Paint();
        pointPaint3 = new Paint();
        pointPaint4 = new Paint();

        paintList=new ArrayList<>();
        paintList.add(pointPaint1);
        paintList.add(pointPaint2);
        paintList.add(pointPaint3);
        paintList.add(pointPaint4);

        for (int i = 0; i < paintList.size(); i++) {
            Paint mPaint = paintList.get(i);
            mPaint.setStrokeWidth(10);
            mPaint.setAntiAlias(true);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setTextAlign(Paint.Align.CENTER);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int lineLength = width / 5;

        //繪制底部長(zhǎng)灰線
        canvas.drawLine(0, lineHeight, width, lineHeight, grayPaint);

        drawProgress(canvas, lineLength);
    }


    /**
     * 畫進(jìn)度
     *
     * @param canvas
     * @param lineLength 每個(gè)區(qū)間的平均長(zhǎng)度
     */
    private void drawProgress(Canvas canvas, int lineLength) {

        //在V0~V1區(qū)間內(nèi)
        if (currentValues >= v0Values && currentValues < v1Values) {
            int stopX = currentValues * lineLength / (v1Values - v0Values);
            //x起始位置婴谱,y起始位置蟹但,x停止位置,y停止位置
            offsetX = stopX;
            pointPaint1.setColor(Color.RED);
            pointPaint2.setColor(Color.GRAY);
            pointPaint3.setColor(Color.GRAY);
            pointPaint4.setColor(Color.GRAY);
        } else if (currentValues >= v1Values && currentValues < v2Values) {
            //在V1~V2區(qū)間內(nèi)
            int stopX = (currentValues - v1Values) * lineLength / (v2Values - v1Values);
            offsetX = lineLength * 1 + stopX;
            pointPaint1.setColor(Color.RED);
            pointPaint2.setColor(Color.GRAY);
            pointPaint3.setColor(Color.GRAY);
            pointPaint4.setColor(Color.GRAY);
        } else if (currentValues >= v2Values && currentValues < v3Values) {
            //在V2~V3區(qū)間內(nèi)
            int stopX = (currentValues - v2Values) * lineLength / (v3Values - v2Values);
            offsetX = lineLength * 2 + stopX;
            pointPaint1.setColor(Color.RED);
            pointPaint2.setColor(Color.RED);
            pointPaint3.setColor(Color.GRAY);
            pointPaint4.setColor(Color.GRAY);
        } else if (currentValues >= 00 && currentValues <= v4Values) {
            //在V3~V4區(qū)間內(nèi)
            int stopX = (currentValues - v3Values) * lineLength / (v4Values - v3Values);
            offsetX = lineLength * 3 + stopX;
            pointPaint1.setColor(Color.RED);
            pointPaint2.setColor(Color.RED);
            pointPaint3.setColor(Color.RED);
            pointPaint4.setColor(Color.GRAY);
        } else if (currentValues > v4Values) {
            int stopX = 10;//超過8萬使用固定值
            offsetX = lineLength * 4 + stopX;
            pointPaint1.setColor(Color.RED);
            pointPaint2.setColor(Color.RED);
            pointPaint3.setColor(Color.RED);
            pointPaint4.setColor(Color.RED);
        }

        canvas.drawLine(0, lineHeight, offsetX, lineHeight, paint);


        //圓心的XY坐標(biāo)谭羔,圓心半徑
        canvas.drawCircle(1 * lineLength - pointSize, pointSize, pointSize, pointPaint1);
        canvas.drawCircle(2 * lineLength - pointSize, pointSize, pointSize, pointPaint2);
        canvas.drawCircle(3 * lineLength - pointSize, pointSize, pointSize, pointPaint3);
        canvas.drawCircle(4 * lineLength - pointSize, pointSize, pointSize, pointPaint4);

        if (callback != null) {
            callback.callBack(offsetX,currentValues);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = this.getMeasuredWidth();
        hight = this.getMeasuredHeight();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    public void getOffsetX(MyCallback callback){
        this.callback=callback;
    }

    public interface MyCallback {
        public void callBack(int offsetX,int currentValues);
    }

}

2华糖、布局代碼

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/ll_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:orientation="vertical">
    </LinearLayout>

    <com.wj.progressbardemo.GrowthValueProgress
        android:id="@+id/progress"
        android:layout_marginTop="3dp"
        android:layout_width="match_parent"
        android:layout_height="6dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.5" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="V1會(huì)員\n100" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="V2會(huì)員\n10000" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="V3會(huì)員\n40000" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="V4會(huì)員\n80000" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.5" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp">

        <EditText
            android:id="@+id/et_text"
            android:layout_width="100dp"
            android:layout_height="40dp" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="btnSetValues"
            android:text="設(shè)置" />

    </LinearLayout>
</LinearLayout>

ok,那么就有疑問了,線條上面的黑色會(huì)話框口糕,是該怎么搞呢缅阳,我的想法是在View之外搞,根據(jù)接口回調(diào)景描,我能知道我的紅色的線有多長(zhǎng)十办,也就相當(dāng)于我知道我的黑色會(huì)話框距離左邊多遠(yuǎn)

3、設(shè)置黑色會(huì)話框

package com.wj.progressbardemo;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private int values=100;
    private EditText et_text;
    private GrowthValueProgress progress;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        progress = (GrowthValueProgress) findViewById(R.id.progress);
        final LinearLayout ll_content= (LinearLayout) findViewById(R.id.ll_content);
        et_text = (EditText) findViewById(R.id.et_text);

        progress.setCurrentValues(values);

        progress.getOffsetX(new GrowthValueProgress.MyCallback() {
            @Override
            public void callBack(int offsetX,int currentValues) {
                TextView tv=new TextView(MainActivity.this);
                tv.setBackgroundResource(R.drawable.ic_growth_values);
                if (currentValues>80000){
                    tv.setText(8+"萬+成長(zhǎng)值");
                }else{
                    tv.setText(currentValues+"成長(zhǎng)值");
                }
                tv.setTextColor(Color.WHITE);
                tv.setTextSize(10);
                tv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT));
                ll_content.removeAllViews();
                LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tv.getLayoutParams();
                params.setMargins(offsetX,0,0,0);
                ll_content.addView(tv);
            }
        });
    }

    public void btnSetValues(View view) {
        String trim = et_text.getText().toString().trim();
        progress.setCurrentValues(Integer.parseInt(trim));
        progress.invalidate();
    }
}

看看結(jié)果:
image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末超棺,一起剝皮案震驚了整個(gè)濱河市向族,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棠绘,老刑警劉巖件相,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件再扭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡夜矗,警方通過查閱死者的電腦和手機(jī)泛范,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來紊撕,“玉大人罢荡,你說我怎么就攤上這事《苑觯” “怎么了区赵?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)浪南。 經(jīng)常有香客問我笼才,道長(zhǎng),這世上最難降的妖魔是什么络凿? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任骡送,我火速辦了婚禮,結(jié)果婚禮上喷众,老公的妹妹穿的比我還像新娘各谚。我一直安慰自己,他們只是感情好到千,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赴穗,像睡著了一般憔四。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上般眉,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天了赵,我揣著相機(jī)與錄音,去河邊找鬼甸赃。 笑死柿汛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的埠对。 我是一名探鬼主播络断,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼项玛!你這毒婦竟也來了貌笨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤襟沮,失蹤者是張志新(化名)和其女友劉穎锥惋,沒想到半個(gè)月后昌腰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膀跌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年遭商,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捅伤。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡劫流,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出暑认,到底是詐尸還是另有隱情困介,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布蘸际,位于F島的核電站座哩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏粮彤。R本人自食惡果不足惜根穷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望导坟。 院中可真熱鬧屿良,春花似錦、人聲如沸惫周。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽递递。三九已至喷橙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間登舞,已是汗流浹背贰逾。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留菠秒,地道東北人疙剑。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像践叠,于是被迫代替她去往敵國和親言缤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容