Android之旅Android开发经验谈技术干货

Android 扇形统计图

2017-12-26  本文已影响64人  Android师哥
night_rain.png

Android 开发中不可避免的会有一些统计的需求,为了应对千变万化的需求,作为我们开发者就需要学会利用Android暴露给我们的接口,来绘制我们自己的View;

首先继承View

    //用户数据
    private List<Integer> mNumbers = new ArrayList<>();
    //用户指定的颜色
    private List<Integer> mColors = new ArrayList<>();
    //用户指定的提示内容
    private List<String> hintContents = new ArrayList<>();
    //用户指定文字的颜色
    private int textColor = Color.parseColor("#000000");
    //用户指定线条的颜色
    private int lineColor = Color.parseColor("#000000");
    //用户数据的总数
    private int sum = 0;
    //控件的高度
    private int mMeasuredHeight;
    //控件的宽度
    private int mMeasuredWidth;
    //中心点坐标
    private float cirX;
    private float cirY;

public class StatisticsCircle extends View {

    public StatisticsCircle(Context context) {
        super(context);
    }

    public StatisticsCircle(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    public StatisticsCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }
}

初始化画笔

既然要绘制自己的view,画笔是必不可少的

    /**
     * 初始化画笔
     */
    private void initPaint() {
        initPicPaint();
        initLinePaint();
        initTextPaint();
    }

    /**
     * 绘制文字画笔
     */
    private void initTextPaint() {
        mTextPaint = new Paint();
        //设置抗锯齿
        mTextPaint.setAntiAlias(true);
        //图像抖动处理
        mTextPaint.setDither(true);
        //填充和描边
        mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        //设置线和文字的颜色
        mTextPaint.setColor(textColor);
        //设置文字的大小
        mTextPaint.setTextSize(CommonUtil.getConverUtil().converSp2Px(10));
    }

    /**
     * 绘制直线画笔
     */
    private void initLinePaint() {
        mLinPaint = new Paint();
        mLinPaint.setAntiAlias(true);
        mLinPaint.setDither(true);
        mLinPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        //设置画笔的宽度
        mLinPaint.setStrokeWidth(CommonUtil.getConverUtil().convertDp2Px(1));
        //设置画笔的颜色
        mLinPaint.setColor(lineColor);
    }

    /**
     * 绘制弧形的画笔
     */
    private void initPicPaint() {
        mPicPaint = new Paint();
        //抗锯齿
        mPicPaint.setAntiAlias(true);
        //抖动处理
        mPicPaint.setDither(true);
        //填充和描边
        mPicPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

绘制逻辑

画笔准备好了,就要在Android给我们的画布上进行绘制了


绘制弧形

绘制第一段直线

绘制第二段直线

绘制小圆点
    private void drawHorizontal(Canvas canvas) {
        //绘制圆形的区域
        RectF mRectF = new RectF();
        //判断文字的高度
        Rect mJudgeRect = ijudgePaintTextHeight(mTextPaint, "判断");
        //文字的高度
        int mJudgeHeight = mJudgeRect.height();
        /*
        *获取圆的直径
        *控件的高-文字的高(给上下写字预留空间)-划线的最高值(划线最长为高度的1/8)
        */
        float diameter = mMeasuredHeight - mJudgeHeight * 2 - mMeasuredHeight / 4 - CommonUtil.getConverUtil().convertDp2Px(10);
        //获取圆的半径
        float radius = diameter / 2;
        //设置圆形的区域
        mRectF.set(cirX - radius,
                (mMeasuredHeight - diameter) / 2,
                diameter + (cirX - radius),
                (mMeasuredHeight - diameter) / 2 + diameter);
        //第一次绘制角度
        float startAngle = 270;
        //绘制过的角度
        float drawAngle = 0;
        for (int i = 0; i < mNumbers.size(); i++) {
            //获取第一个数据
            int number = mNumbers.get(i);
            //计算需要绘制的角度
            float angle = ((float) number / sum) * 360;
            //设置每次绘制时画笔的颜色
            mPicPaint.setColor(mColors.get(i));
            //开始绘制扇形
            canvas.drawArc(mRectF, startAngle, angle, true, mPicPaint);
            //计算下一次开始绘制扇形的角度
            startAngle = (startAngle + angle) >= 360 ? ((startAngle + angle) - (float) 360) : (startAngle + angle);
            //计算绘制过的角度
            drawAngle += angle;
            //计算绘制第一段直线开始的坐标X
            float startX = (float) (Math.sin((drawAngle - angle / 2) * Math.PI / 180) * (radius - mMeasuredHeight / 8) + cirX);
            //计算绘制第一段直线开始的坐标Y
            float startY = cirY - (float) (Math.cos((drawAngle - angle / 2) * Math.PI / 180) * (radius - mMeasuredHeight / 8));
            //计算绘制第一段直线结束的坐标X
            float middleX = (float) (Math.sin((drawAngle - angle / 2) * Math.PI / 180) * (radius + (mMeasuredHeight / 8)) + cirX);
            //计算绘制第一段直线结束的坐标Y
            float middleY = cirY - (float) (Math.cos((drawAngle - angle / 2) * Math.PI / 180) * (radius + (mMeasuredHeight / 8)));
            //计算第二段直线绘制结束的坐标X
            float endX = 0;
            //结束位置小圆点开始X轴坐标
            float startMinCircularX = 0;
            //通过判断结束X轴的坐标相对圆形位置来确定坐标
            float startTextX = 0;
            //文本内容
            String content = hintContents.get(i) + "(" + CommonUtil.getConverUtil().converPercent(sum, number) + ")";
            Rect mRect = ijudgePaintTextHeight(mTextPaint, content);
            if (middleX > cirX) {
                endX = cirX + radius + mMeasuredHeight / 8;
                startMinCircularX = endX + CommonUtil.getConverUtil().convertDp2Px(2);
                startTextX = startMinCircularX + CommonUtil.getConverUtil().convertDp2Px(5);
            } else if (middleX < cirX) {
                endX = cirX - radius - mMeasuredHeight / 8;
                startMinCircularX = endX - CommonUtil.getConverUtil().convertDp2Px(2);
                startTextX = startMinCircularX - mRect.width() - CommonUtil.getConverUtil().convertDp2Px(5);
            } else {
                endX = cirX - radius - mMeasuredHeight / 8;
                startMinCircularX = endX - CommonUtil.getConverUtil().convertDp2Px(2);
                startTextX = startMinCircularX - CommonUtil.getConverUtil().convertDp2Px(5);
            }
            //计算第二段直线绘制结束的坐标Y
            float endY = middleY;
            //绘制第一段直线
            canvas.drawLine(startX, startY, middleX, middleY, mLinPaint);
            //绘制第二段直线
            canvas.drawLine(middleX, middleY, endX, endY, mLinPaint);
            //绘制黑色小圆点
            canvas.drawCircle(startMinCircularX, endY, CommonUtil.getConverUtil().convertDp2Px(2), mLinPaint);
            //绘制文字
            canvas.drawText(content, startTextX, endY + mJudgeRect.height() / 2, mTextPaint);
        }
    }

效果图

扇形统计图简单效果.png

学习自绘控件做的一个Demo,大概的实现了效果,不足之处还请提出,共同进步!

上一篇 下一篇

猜你喜欢

热点阅读