自定义View——成长值、积分进度条

2017-10-25  本文已影响0人  烂吹笙
产品需求中难免有一些不符合常理的设计!!!今天来设计针对一个会员,积分系统,设计一个水平的进度条,首先看图说话 image

看出图中会员等级分为4级,每一级的长度均分4个实心的点,分为四个区间,每个区间中设置均分的进度,所以用普通的ProgressBar、SeekBar是无法实现的,所以必须自定义View,使用画笔画。

1、画线

我的思路就是先画一条灰色的虚线,让后,画四个点,根据传入的当前的成长值,计算出在哪个区间,进而绘画出红色的线,并且设置实心的红点的点

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;

/**
 * 成长值进度条
 */

public class GrowthValueProgress extends View {

    private MyCallback callback;

    private Context context;

    private int currentValues = 1100;//当前成长值

    private int v0Values = 0;//v0会员成长值

    private int v1Values = 100;//v1会员成长值

    private int v2Values = 10000;//v2会员成长值

    private int v3Values = 40000;//v3会员成长值

    private int v4Values = 80000;//v4会员成长值

    private Paint paint;//会员画笔

    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的坐标;

    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;//线的高度设置为布局的一半高度
        pointSize=hight/2;//圆点的半径设置为布局的一半高度

        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;

        //绘制底部长灰线
        canvas.drawLine(0, lineHeight, width, lineHeight, grayPaint);

        drawProgress(canvas, lineLength);
    }


    /**
     * 画进度
     *
     * @param canvas
     * @param lineLength 每个区间的平均长度
     */
    private void drawProgress(Canvas canvas, int lineLength) {

        //在V0~V1区间内
        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区间内
            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区间内
            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区间内
            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坐标,圆心半径
        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会员\n100" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="V2会员\n10000" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="V3会员\n40000" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="V4会员\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="设置" />

    </LinearLayout>
</LinearLayout>

ok,那么就有疑问了,线条上面的黑色会话框,是该怎么搞呢,我的想法是在View之外搞,根据接口回调,我能知道我的红色的线有多长,也就相当于我知道我的黑色会话框距离左边多远

3、设置黑色会话框

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+"万+成长值");
                }else{
                    tv.setText(currentValues+"成长值");
                }
                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();
    }
}

看看结果: image
上一篇下一篇

猜你喜欢

热点阅读