• 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;
        }
    }
    
  • 相关阅读:
    Linux network driver
    Linux dd
    Linux aclocal
    Ubuntu
    Makefile
    控制导出符号
    Apache
    Linux nm命令
    Git Submodule
    Linux sed
  • 原文地址:https://www.cnblogs.com/pengjingya/p/14952710.html
Copyright © 2020-2023  润新知