自定义进度条(可用作温度计,不规则色块,根据数据源变)

 
不规则色块,且每到一个阶段,该色块变色的一个自定义进度条view

    直接上图和代码

所有颜色可配,色块数量根据数据动态可变,边上带的标签没放出来,有需要可以找我,根据该view暴露出来的方法很容易算出来。 

暂时没做太多优化,有时间会改一波




/**
 * Created by miaojun on 2018/6/6.
 * mail:1290846731@qq.com
 *
 * 可独立使用的底部不规则色块的进度条
 */

public class ProgressIrregularView extends View {
    private int mStrokeWidth = 5;//描边宽度
    private float mProgressHigh;//进度条总高度
    private float mProgressWidth;//进度条总宽度
    private int mPartNum;//分隔的份数
    private int mDividerWidth = 5;//分割线的宽度
    private int mBackgroundColor = Color.parseColor("#33ffffff");//底色
    private int mDefaultBlockColor = Color.parseColor("#1a000000");//默认阶段色
    private int mBlockColor = Color.parseColor("#33ff0f50");//当前阶段颜色
    private int mProgressColor = Color.parseColor("#ff0f50");//进度条颜色
    private int mProgressShapeColor = Color.parseColor("#ff6b23");//进度条中间渐变色

    private Paint mPaint;
    private Path mPath;

    private List mDufaultList = new ArrayList();//默认色块坐标

    private float mProp;//当前分数所占比例
    private int mCurrentPart;//当前阶段
    private float[] mProgressPosition;

    private List<DefaultPropBean> mDefaultDataList;//默认色块分隔比例
    private List<Float> mItemHeightList = new ArrayList<>();//各个色块高度
    public ProgressIrregularView(Context context) {
        super(context);
        init();
    }

    public ProgressIrregularView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init(){
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        mPaint = new Paint();
        mPath = new Path();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(mProgressHigh == 0){
            this.mProgressHigh = getMeasuredHeight();
            this.mProgressWidth = getMeasuredWidth();
            setProgress(mProp);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawBackground(canvas);
        computeDefaultBlockPositionData();
        drawDefaultBlock(canvas);
        if(mProgressPosition != null && mProgressPosition.length != 0 && mProp != 0){
            float radi = (mProgressWidth - mStrokeWidth * 2) / 2;
            if(Math.abs(mProgressPosition[1] - mProgressPosition[3]) <= radi){
                drawBottomArc(canvas,mProgressColor,mProgressPosition);
            }else if((mProgressHigh - 2 * mStrokeWidth) - Math.abs(mProgressPosition[1] - mProgressPosition[3]) <= radi){
                drawTopArc(canvas,mProgressColor,mProgressPosition);
            }else{
                drawBottomFilletBlock(canvas,mProgressColor,mProgressPosition);
            }

        }
    }

    //绘制底部背景
    private void drawBackground(Canvas canvas){
        mPaint.reset();
        mPaint.setColor(mBackgroundColor);
        RectF rectF = new RectF(0,0,mProgressWidth,mProgressHigh);
        canvas.drawRoundRect(rectF,mProgressWidth/2,mProgressWidth/2, mPaint);
    }

    //绘制默认方形色块
    private void drawDefaultBlock(Canvas canvas){
        if(mDufaultList.size() == 0){
            return;
        }
        if(mDufaultList.size() == 1){
            drawOneDefaultBlock(canvas,mDefaultBlockColor, (float[]) mDufaultList.get(0));
            return;
        }
        int currentColor;
        for(int i = 0; i < mDufaultList.size(); i++){
            if(i >= mPartNum - mCurrentPart){
                currentColor = mBlockColor;
            }else{
                currentColor = mDefaultBlockColor;
            }
            if(i == 0){
                drawTopFilletBlock(canvas,currentColor,(float[]) mDufaultList.get(i));
            } else if(i == mDufaultList.size() - 1){
                drawBottomFilletBlock(canvas,currentColor,(float[]) mDufaultList.get(i));
            } else{
                drawSquareBlock(canvas,currentColor,(float[]) mDufaultList.get(i));
            }
        }
    }


    //计算默认阶段坐标
    private void computeDefaultBlockPositionData(){
        if(mDufaultList.size() != 0 || mDefaultDataList.size() == 0){
            return;
        }

        float left = mStrokeWidth;
        float right = mProgressWidth - mStrokeWidth;
        float top,bottom,itemHigh;
        mPartNum = mDefaultDataList.size();

        for(int i = 0; i < mPartNum; i++){
            itemHigh = (mProgressHigh - mStrokeWidth * 2 - (mPartNum - 1) * mDividerWidth) * mDefaultDataList.get(i).getProp();
            top = mStrokeWidth + getItemSum() + i * mDividerWidth;
            mItemHeightList.add(itemHigh);
            bottom = top + itemHigh;
            float[] itemPosition = {left,top,right,bottom};
            mDufaultList.add(itemPosition);
        }
    }

    private float getItemSum(){
        if(mItemHeightList.size() == 0){
            return 0;
        }
        float sum = 0;
        for(float i : mItemHeightList){
            sum = sum + i;
        }
        return sum;
    }

    //绘制矩形色块
    private void drawSquareBlock(Canvas canvas,int color,float[] position){
        mPaint.reset();
        mPaint.setColor(color);
        RectF rectF = new RectF(position[0],position[1],position[2],position[3]);
        canvas.drawRect(rectF,mPaint);
    }

    //绘制上圆角色块
    private void drawTopFilletBlock(Canvas canvas,int color,float[] position){
        mPath.reset();
        mPaint.reset();
        mPaint.setColor(color);
        RectF rectF = new RectF(position[0],position[1],position[2],position[3]);
        float radi = (mProgressWidth - mStrokeWidth * 2) / 2;
        float[] topRadii={radi,radi,radi,radi,0f,0f,0f,0f};
        mPath.addRoundRect(rectF,topRadii, Path.Direction.CW);
        canvas.drawPath(mPath, mPaint);
    }

    //绘制圆角矩形&矩形相交(头部半圆部分)
    private void drawTopArc(Canvas canvas,int color,float[] position){
        int layoutId = canvas.saveLayer(0,0,mProgressWidth,mProgressHigh,null,Canvas.ALL_SAVE_FLAG);
        RectF rectF = new RectF(position[0],mStrokeWidth,position[2],position[1]);
        if(position[1] == mStrokeWidth){
            return;
        }else{
            position[1] = mStrokeWidth;
        }
        drawOneDefaultBlock(canvas,color,position);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRect(rectF,mPaint);
        canvas.restoreToCount(layoutId);
    }

    //绘制下半圆
    private void drawBottomArc(Canvas canvas,int color,float[] position){
        mPaint.reset();
        mPaint.setColor(color);
        float radi = (mProgressWidth - mStrokeWidth * 2) / 2;
        double angle = Math.toDegrees(Math.acos((radi - Math.abs(position[1]-position[3]))/radi) * 2);//圆弧角度
        RectF rectF = new RectF(position[0],mProgressHigh - mStrokeWidth - radi * 2,position[2],mProgressHigh - mStrokeWidth);
        canvas.drawArc(rectF,(float) ((180 - angle)/2),(float) angle,false,mPaint);
    }

    //绘制下圆角色块
    private void drawBottomFilletBlock(Canvas canvas,int color,float[] position){
        mPaint.reset();
        mPaint.setColor(color);
        RectF rectF = new RectF(position[0],position[1],position[2],position[3]);
        float radi = (mProgressWidth - mStrokeWidth * 2) / 2;
        float[] bottomRadii={0f,0f,0f,0f,radi,radi,radi,radi};
        Shader shader = new LinearGradient(0,mStrokeWidth+radi,0,mProgressHigh-mStrokeWidth,new int[] {mProgressColor,mProgressShapeColor,mProgressColor},null, Shader.TileMode.REPEAT);
        mPaint.setShader(shader);
        mPath.reset();
        mPath.addRoundRect(rectF,bottomRadii, Path.Direction.CW);
        canvas.drawPath(mPath, mPaint);
    }

    //上下都是圆角(只有一个默认色块)
    private void drawOneDefaultBlock(Canvas canvas,int color,float[] position){
        mPaint.reset();
        mPaint.setColor(color);
        float radii = (mProgressWidth - mStrokeWidth * 2) / 2;
        RectF rectF = new RectF(position[0],position[1],position[2],position[3]);
        canvas.drawRoundRect(rectF,radii,radii, mPaint);
    }

    private int getCurrentPart(float prop){
        float part = 0;
        for(int i = mDefaultDataList.size() - 1; i >= 0; i--){
            part = part + mDefaultDataList.get(i).getProp();
            if(part > prop){
                return mDefaultDataList.size() - i;
            }
        }
        return 1;
    }

    //设置当前进度
    private void setProgress(float prop){
        if(mProgressHigh == 0){
            return;
        }
        float left = mStrokeWidth;
        float progressHigh = prop * (mProgressHigh - mStrokeWidth * 2);
        float top = mProgressHigh - mStrokeWidth - progressHigh;
        float right = mProgressWidth - mStrokeWidth;
        float bottom = mProgressHigh - mStrokeWidth;
        mProgressPosition = new float[]{left, top, right, bottom};
    }

    /**
     * 配置进度条色值  默认0  不重设颜色
     * @param defaultBgColor  默认色块颜色
     * @param progressColor 进度条主色
     * @param progressShapeColor 进度条中间渐变色
     * @param currentPartColor 当前色块颜色
     */
    public void initSetting(int defaultBgColor,int progressColor,int progressShapeColor,int currentPartColor){
        if(defaultBgColor != 0){
            mDefaultBlockColor = defaultBgColor;
        }
        if(progressColor != 0){
            mProgressColor = progressColor;
        }
        if(progressShapeColor != 0){
            mProgressShapeColor = progressShapeColor;
        }
        if(currentPartColor != 0){
            mBlockColor = currentPartColor;
        }
    }

    /**
     * 设置当前分数所占比例
     * @param prop
     */
    public void setCurrentProp(float prop){
        if(mProp == prop){
            return;
        }
        mProp = prop;
        mCurrentPart = getCurrentPart(prop);
        setProgress(prop);
        invalidate();
    }

    //设置默认数据
    public void setDefaultData(List<DefaultPropBean> list){
        if(mDefaultDataList == null){
            mDefaultDataList = new ArrayList<>();
            mDefaultDataList.addAll(list);
            Collections.reverse(mDefaultDataList);//倒序
        }

    }

    //获取各阶段高度
    public List<Float> getItemHeightList(){
        return mItemHeightList;
    }

    //获取分隔线高度
    public int getStrokeWidth(){
        return mStrokeWidth;
    }

    //获取当前阶段
    public int getCurrentPart(){
        return mCurrentPart;
    }
}
//数据mode
 
public class DefaultPropBean {
    private float prop;//比例
    private String msg;

    public DefaultPropBean(float prop, String msg){
        this.prop = prop;
        this.msg = msg;
    }

    public float getProp() {
        return prop;
    }

    public void setProp(float prop) {
        this.prop = prop;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}
//数据demo
List<DefaultBean> list = new ArrayList<DefaultBean>();
list.add(new DefaultBean(0.2f,"1111"));
list.add(new DefaultBean(0.3f,"2222"));
list.add(new DefaultBean(0.2f,"3333"));
list.add(new DefaultBean(0.1f,"4444"));
list.add(new DefaultBean(0.2f,"5555"));


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值