美文网首页
Android——自定义View(四)

Android——自定义View(四)

作者: 如愿以偿丶 | 来源:发表于2020-10-10 15:48 被阅读0次

1.概述

  最近公司要让做一个类似仪表盘样式的View,也学习了一些,来记录一下实现步骤。

2.效果

1.仪表盘

image.png

2.饼图

image.png

3.实现思路

3.1.仪表盘实现思路

  1.首先画一个圆弧,定义圆心,起始角度,扫过的角度。
  2.绘制圆弧上的每一个刻度。使用PathEffect,他的其中一个子类PathDashPathEffect来设置(细节一会代码详细指名)
  3.绘制最后的指针

3.2.饼图实现思路

  1.绘制圆弧,分别设置每一个圆弧的角度。和颜色。
  2.单独处理第二块突出的圆弧。绘制该块圆弧时,我们先将画布平移。再进行绘制

4.代码实现

4.1.仪表盘

/**
 * 仪表盘
 */
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class DashBoard extends View {
    private Paint mPaint;
    private Path mPath;
    private PathDashPathEffect effect;
    private static final float angle = 120;
    private static final float radius = UIUtils.dp2px(150);

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

    //执行在super之后
    {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStrokeWidth(UIUtils.dp2px(2));
        mPaint.setStyle(Paint.Style.STROKE);
        mPath = new Path();
        mPath.addRect(0,0,UIUtils.dp2px(2),UIUtils.dp2px(10), Path.Direction.CW);  //添加一个矩形


        Path arg = new Path();
        arg.addArc(getWidth() / 2 - radius,getHeight() / 2 - radius,getWidth() / 2 + radius,getHeight() / 2 + radius,90 + angle / 2,360 - angle);
        PathMeasure measure = new PathMeasure(arg,false);   //获取圆弧长度,  绘制20个刻度,先减去一个刻度的宽度在除以20
        /**
         * advance:每一个刻度之间的距离
         * phase:起始的刻度需要空出的距离
         */
        effect = new PathDashPathEffect(mPath,  (measure.getLength() - UIUtils.dp2px(2)) / 20,0, PathDashPathEffect.Style.ROTATE);
//        mPaint.setPathEffect(new PathDashPathEffect(mPath,50,0, PathDashPathEffect.Style.ROTATE));
    }

    /**
     * 该方法调用是在onLayout之后,如果实际尺寸改变了他会调用一次,否则不调用
     * 好处:1.每次尺寸发生改变是Path就会被重置,重新绘制
     *      2.不会过度的绘制
     *      3.
     *    Path.Direction.CW: 顺时针
     *    Path.Direction.CCW:逆时针
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
//        mPaint.reset();
//        mPath.addRect(getWidth() / 2 - 150,getHeight() / 2 - 300 ,getWidth() / 2 + 150,getHeight() / 2 , Path.Direction.CCW);
//        mPath.addCircle(getWidth() / 2,getHeight() / 2 ,150, Path.Direction.CW);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        mPath.setFillType(Path.FillType.EVEN_ODD);
//        canvas.drawLine(100,100,300,300,mPaint);
//        canvas.drawPath(mPath,mPaint);
        //画线
        canvas.drawArc(getWidth() / 2 - radius,getHeight() / 2 - radius,getWidth() / 2 + radius,getHeight() / 2 + radius,90 + angle / 2,360 - angle,false,mPaint);
        /**
         * advance:每一个刻度之间的距离
         * phase:起始的刻度需要空出的距离
         */
        //画刻度
        mPaint.setPathEffect(effect);
        //画线
        canvas.drawArc(getWidth() / 2 - radius,getHeight() / 2 - radius,getWidth() / 2 + radius,getHeight() / 2 + radius,90 + angle / 2,360 - angle,false,mPaint);
        mPaint.setPathEffect(null);

        //画指针
        canvas.drawLine(getWidth() / 2 ,getHeight() / 2,
                (float) Math.cos(Math.toRadians(getAngleFromeMark(5))) * UIUtils.dp2px(120) + getWidth() / 2,
                (float) Math.sin(Math.toRadians(getAngleFromeMark(5))) * UIUtils.dp2px(120) + getHeight() / 2,
                        mPaint);
    }

     public int getAngleFromeMark(int mark){
        return (int) (90 + angle / 2 + (360 - angle) / 20 * mark);
     }

}

4.2.饼图

/**
 * 饼图
 * 实现思路:
 *      1.循环绘制相应的圆弧
 *      2.每次修改画笔的颜色,修改圆弧的起始和扫描过的角度。
 *      3.当绘制凸起的圆弧时平移画布,进行绘制
 *      4.绘制完成后恢复画布
 */
public class PieChart extends View {
    private Paint mPaint;
    private static final float radius = UIUtils.dp2px(150);
    private static final float TYPE_TWO = 2;

    private int[] angle = {60,100,120,80};  //角度
    private int[] colors = {Color.parseColor("#817936"),Color.parseColor("#444693"),Color.parseColor("#f391a9"),Color.parseColor("#826858")}; //颜色

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

    {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//        mPaint.setStyle(Paint.Style.STROKE);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int currentAngle = 0;  //当前角度
        for (int i = 0; i < angle.length; i++) {
            mPaint.setColor(colors[i]);
            canvas.save();
            if (i == TYPE_TWO){
                canvas.translate(-30,-30); //将画布平移  此处简单处理,需要根据角度计算。
            }
            canvas.drawArc(getWidth() / 2 -radius,getHeight() / 2 - radius ,getWidth() / 2 + radius,getHeight() / 2 + radius,currentAngle,angle[i],true,mPaint);
            canvas.restore();
            currentAngle+=angle[i];    //每次绘制玩,当前角度递增
        }
    }
}

相关文章

网友评论

      本文标题:Android——自定义View(四)

      本文链接:https://www.haomeiwen.com/subject/ouqjpktx.html