36、AndroidCanvas画布

Canvas VS Paint

Canvas方法

系统提供Canvas对象来提供绘图方法,其中Paint常见的属性如下:

mPaint.setAntiAlias() // 设置画笔的锯齿效果
mPaint.setColor() // 设置画笔的颜色
mPaint.setARGB() // 设置画笔的A、R、G、B值
mPaint.setAlpha() // 设置画笔的Alpha值
mPaint.setTextSize() // 设置字体的尺寸
mPaint.setStyle() // 设置画笔的风格(空心或实心)
mPaint.setStrokeWidth() // 设置空心边框的宽度

下面我们来看看Canvas一些简单的绘制:

// 绘制点
canvas.drawPoint(x, y, paint);  
// 绘制直线
canvas.drawLine(startX, startY, stopX, stopY, paint);
// 绘制多条直线
float[] pts = {
    startX1, startY1, endX1, endY1,
    ......
    startXn, startYn, endXn, endYn};
canvas.drawLines(pts, paint);  
// 绘制矩形
canvas.drawRect(left, top, right, bottom, paint);
// 绘制圆角矩形
canvas.drawRoundRect(left, top, right, bottom, rx, ry, paint);  
// 绘制圆
canvas.drawCircle(cx, cy, radius, paint);  
// 绘制弧线,这里需要注意绘制弧线和扇形的区分就是倒数第二个参数useCenter的值,true或false。
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);  
// 绘制椭圆
canvas.drawOval(left, top, right, bottom, paint);  
// 绘制文本
canvas.drawText(text, x, y, paint);  
// 在指定位置绘制文本
canvas.drawPosText(text, 
        new float[]{
        X1, Y1,
        ......
        Xn, Yn}, paint);  
        
// 绘制路径
Path path = new Path();
path.moveTo(50, 50);
path.lineTo(100, 100);
path.lineTo(100, 300);
canvas.drawPath(path, mPaint);  

Canvas实例

Canvas作为绘制图像的直接对象,提供以下几个非常有用的方法:

Canvas.save(): 保存画布,将之前所有已经绘制的图像保存起来,让后续操作在新的图层上操作。
Canvas.restore() 合并图层操作,它的作用是将save()之后绘制的所有图像与save()之前的图像进行合并。
Canvas.translate() 和 Canvas.rotate():画布的坐标系的翻转和偏移。

绘制仪表盘实例

  • 仪表盘 --- 外面的大圆盘
  • 刻度线 --- 包含四个长的刻度线和其他短的刻度线
  • 刻度值 --- 包含长刻度线对应的大的刻度值和其他小的刻度值
  • 指针 --- 中间的指针,一粗一细两根指针

public class KeDuPanView extends View {
    private int mWidth;
    private int mHeight;
    public KeDuPanView(Context context) {
        this(context, null);
    }
    public KeDuPanView(Context context, AttributeSet attrs) {
        super(context, attrs);
        WindowManager wManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mWidth = wManager.getDefaultDisplay().getWidth();
        mHeight = wManager.getDefaultDisplay().getHeight();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {      
        // 画外圆
        Paint paintCircle = new Paint();
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setAntiAlias(true);
        paintCircle.setStrokeWidth(5);
        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle);
        
        // 画刻度
        Paint paintDegree = new Paint();
        paintDegree.setStrokeWidth(3);
        for (int i = 0; i < 24; i++) {
            // 区分整点和非整点
            if(i == 0 || i== 6 || i == 12 || i == 18){
                paintDegree.setStrokeWidth(5);
                paintDegree.setTextSize(18);
                // 画长刻度
                canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, 
                        mWidth / 2, mHeight / 2 - mWidth / 2 + 30, paintDegree);
                // 画数字
                String degree = String.valueOf(i);
                canvas.drawText(degree, mWidth / 2 - paintDegree.measureText(degree) / 2,
                        mHeight / 2 - mWidth / 2 + 45, paintDegree);
            }else{
                // 画短刻度
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(15);
                canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2, mWidth / 2, 
                        mHeight / 2 - mWidth / 2 + 15, paintDegree);
                
                // 画数字
                String degree = String.valueOf(i);
                canvas.drawText(degree, mWidth / 2 - paintDegree.measureText(degree) / 2, 
                        mHeight / 2 - mWidth / 2 + 30, paintDegree);
            }
            // 通过旋转画布简化坐标运算
            canvas.rotate(15, mWidth / 2, mHeight / 2);
        }      
        // 画中间指针,时针和分针
        Paint paintHour = new Paint();
        paintHour.setStrokeWidth(10);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(5);
        canvas.save();
        // 开始位置移动到屏幕中心点
        canvas.translate(mWidth / 2, mHeight / 2);
        canvas.drawLine(0, 0, 50, 50, paintHour);
        canvas.drawLine(0, 0, 50, 100, paintMinute);
        canvas.restore();
    }
}  

绘制螺旋图

绘制螺旋图可以主要是掌握绘制圆弧的API,实现效果如下:

代码如下所示:

public class PieCharView extends View {
    private Paint mPaint = new Paint();
    private Paint mTextPaint = new Paint();
    private int mRadius;
    private int mWidth;
    private int mHeight;
    // 绘制不规则扇形
    private int offset; // 中心点偏移坐标
    private int startAngle = -180;
    private int decrement = 50;

    private String[] mColors = new String[]{"#00A200", "#FF7A29", "#F1B766", "#FFBD99", "#008A96", "#E75A41"};
    private int[] mAngles = new int[]{120, 60, 45, 30, 20, 85};

    public PieCharView(Context context) {
        this(context, null);
    }

    public PieCharView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 设置扇形画笔
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        // 设置文字画笔
        mTextPaint.setColor(Color.parseColor("#794C3D27"));
        mTextPaint.setAntiAlias(true);
        mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mRadius = (mWidth + mHeight) / 2;
        for (int i = 0; i <= 5; i ++){
            mPaint.setColor(Color.parseColor(mColors[i]));
            RectF rectF = new RectF(0, 0, mRadius, mRadius);
            offset = (decrement / 2) * i;
            rectF.offset(offset, offset);
            int angle = mAngles[i];
            canvas.drawArc(rectF, startAngle, angle, true, mPaint);
            mRadius = mRadius - decrement;
            startAngle = startAngle + angle;
        }

        // 绘制中心圆
        mPaint.reset();
        mPaint.setColor(Color.parseColor("#FFFFFF"));
        mRadius = mRadius - decrement;
        canvas.drawCircle(mWidth / 2, mHeight / 2, mRadius / 2, mPaint);

        // 绘制中心文字
        mTextPaint.setTextSize(45);
        String text = "总入住";
        Rect rect = new Rect();
        mTextPaint.getTextBounds(text, 0, text.length() - 1, rect); // 测量文字高度
        int textHeight = rect.height();
        canvas.drawText("总入住", mWidth / 2, mHeight / 2 - (textHeight / 2), mTextPaint);
        mTextPaint.setTextSize(51);
        mTextPaint.setColor(Color.parseColor("#009E1F"));
        canvas.drawText("500 间", mWidth / 2, mHeight / 2 + (textHeight / 2) + 10, mTextPaint);
    }

    /**测量宽度的代码*/
    private int measureWidth(int measureSpec){
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if(specMode == MeasureSpec.EXACTLY){
            result = specSize;
        }else{
            result = 300;
            if(specMode == MeasureSpec.AT_MOST){
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    /**测量高度的代码*/
    private int measureHeight(int measureSpec){
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if(specMode == MeasureSpec.EXACTLY){
            result = specSize;
        }else{
            result = 300;
            if(specMode == MeasureSpec.AT_MOST){
                result = Math.min(result, specSize);
            }
        }
        return result;
    }
}
原文地址:https://www.cnblogs.com/pengjingya/p/14952710.html