Android自定义控件-彩色进度条

最终效果如下,没使用任何图片,全手工绘制,比较基础,给大家刚入门的做一个总结
这里写图片描述
流程要点
1 初始化
主要是Paint的属性和控件颜色、距离、大小的定义,这些需要在制作过程细心调整

mDefaultWidthm、DefaultHeight 可以在onMeasure()测量的时候定义,表示控件不设置具体大小时的初始化宽高

  private float mLineThickness;
    private int mDefaultHeight;
    private int mDefaultWidth;
    private Paint mLinePaint;
    private Paint mTrianglePaint;
    private int mTriangleLength;
    private float mProgressLength;
    private int mColorBlue;
    private int mColorRed;
    private float mTriangleCenterLength;
    private int mProgress;
    private int mBorderPadding;
   private void init() {
        mColorBlue = getResources().getColor(R.color.blue0DD2FF);
        mColorRed = getResources().getColor(R.color.redFA4254);
        mColorWhite = getResources().getColor(R.color.white);
        final DisplayMetrics metrics = getResources().getDisplayMetrics();
        mDefaultHeight = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                40,metrics);
        mDefaultWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                270,metrics);
       mTriangleLength =(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,metrics);
        mBorderPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5, metrics);
        mTriangleCenterLength = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,7,metrics);
        mProgressLength = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,0,metrics);
        mLineWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, metrics);
        mLineThickness = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, metrics);
        mLinePaint = new Paint();
        mLinePaint.setAntiAlias(true);
        mLinePaint.setStrokeWidth(mLineThickness);
        mTrianglePaint = new Paint();
        /*去锯齿*/
        mTrianglePaint.setAntiAlias(true);
        /*设置paint的颜色*/
        mTrianglePaint.setColor(mColorBlue);
        /*设置paint的 style 为STROKE:空心 Fill实心*/
        mTrianglePaint.setStyle(Paint.Style.FILL);
}

2 绘制
主要为渐变线的绘制和三角形绘制
渐变线可使用LinearGradient来实现,LinearGradient为Shader的子类,可以实现多种渐变效果

构造函数一:从x到y点的渐变,渐变色只有两种

public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
            TileMode tile){
        mType = TYPE_COLOR_START_AND_COLOR_END;
        mX0 = x0;
        mY0 = y0;
        mX1 = x1;
        mY1 = y1;
        mColor0 = color0;
        mColor1 = color1;
        mTileMode = tile;
        init(nativeCreate2(x0, y0, x1, y1, color0, color1, tile.nativeInt));
    }

构造函数二:从x到y点的渐变,渐变色可以多种,并设置渐变的间隔,传递两个数组,前者为渐变色,后者为渐变色的间距,如从0到0.3f再到1f,实现3种渐变色

 public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
            TileMode tile){
        if (colors.length < 2) {
            throw new IllegalArgumentException("needs >= 2 number of colors");
        }
        if (positions != null && colors.length != positions.length) {
            throw new IllegalArgumentException("color and position arrays must be of equal length");
        }
        mType = TYPE_COLORS_AND_POSITIONS;
        mX0 = x0;
        mY0 = y0;
        mX1 = x1;
        mY1 = y1;
        mColors = colors;
        mPositions = positions;
        mTileMode = tile;
        init(nativeCreate1(x0, y0, x1, y1, colors, positions, tile.nativeInt));
    }

而三角形的绘制则需要精确的计算三个点的距离,这里注意绘制线条时要隔开一定间隔(长度为三角形边长一半),同时线条最后也要空出一段间隔否则三角形就显示不全

具体运用看实现代码

@Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        LinearGradient gradient = new LinearGradient(0, 0, getMeasuredWidth(),
                getMeasuredHeight(), new int[]{mColorBlue, Color.WHITE, mColorRed}, new float[]{0f, 0.7f, 1f}, Shader.TileMode.MIRROR);
        //        LinearGradient gradient = new LinearGradient(0, 0, 400, 400, , getResources().getColor(R.color.gowild_grade_redFA4254), Shader.TileMode.MIRROR);
        mLinePaint.setShader(gradient);
        canvas.drawLine(mBorderPadding, 0, getBarLength()+mBorderPadding, 0, mLinePaint);
        Path path = new Path();
        path.moveTo(mProgressLength + mBorderPadding, mLineThickness);
        path.lineTo(getRightBottomX(), getBottomY());
        path.lineTo(getLeftBottomX(), getBottomY());
        path.close();
        canvas.drawPath(path, mTrianglePaint);
    }

3 进度设置
提供一个方法给外界设置进度,关键点在于刷新界面的时机,如果直接在setProgress中调用invalidate(),是无法正常刷新进度的。
正确的做法是在设置进度时保存变量,在onSizeChanged()之中,已经测量完毕界面的时候再刷新进度的位置,这时进度即可正常显示

    public void setProgress(int progress) {
        Logger.d(TAG,"setProgress"+progress);
        if (progress < 0 | progress > 100) {
            return;
        }
        mProgress = progress;
        invalidate();
    } 
@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (mProgress != 0) {
            mProgressLength = (float) mProgress / 100 * getBarLength();
            invalidate();
        }
        super.onSizeChanged(w, h, oldw, oldh);
    }

你可能感兴趣的:(自定义控件)