• Android 自定义 view(三)—— onDraw 方法理解


    前言:

    上一篇已经介绍了用自己定义的属性怎么简单定义一个view《Android 自定义view(二) —— attr 使用》,那么接下来我们继续深究自定义view,下一步将要去简单理解自定义view的一个比较重要的方法 onDraw(Canvas canvas) ,在探究 onDraw方法之前,我们必须先深入了解两个类Paint和Canvas 。

    第一:认识Paint

    在探究onDraw之前首先必须要认识两个类,这里给出非常不错的两个资料参考网站,我也是从这里得到想要知道的东西,简单的说这下面几篇文章已经够我们喝一壶了,这里我就不再献丑了

    http://www.apihome.cn/api/android/Paint.html

    http://www.cnblogs.com/aibuli/p/efef9d774df97c553a8a0c0c3495ba35.html?utm_source=tuicool&utm_medium=referral 

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1105/1907.html 

    http://blog.csdn.net/harvic880925/article/details/39080931

    第二:认识Canvas

    Canvas类简单理解就是表示一块画布,可以在上面画我们想画的东西

    Canvas中的方法很多,Canvas可以绘制的对象有:

    • 弧线(arcs) canvas.
    • 填充颜色(argb和color)
    • Bitmap
    • 圆(circle和oval)
    • 点(point)
    • 线(line)
    • 矩形(Rect)
    • 图片(Picture)
    • 圆角矩形 (RoundRect)
    • 文本(text)
    • 顶点(Vertices)
    • 路径(path)

    canvas.save():把当前的绘制的图像保存起来,让后续的操作相当于是在一个新的图层上的操作。
    canvas.restore(); 把当前画布返回(调整)到上一个save()状态之前
    canvas.translate(dx, dy); //把当前画布的原点移到(dx,dy),后面的操作都以(dx,dy)作为参照点,默认原点为(0,0)

    canvas.scale(x,y);扩大。x为水平方向的放大倍数,y为竖直方向的放大倍数
    canvas.rotate(angel):旋转.angle指旋转的角度,顺时针旋转。
    canvas.transform():切变。所谓切变,其实就是把图像的顶部或底部推到一边。
    canvas.saveLayer(bounds, paint, saveFlags);

    推荐文章:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html

    第三:Canvas 简单使用

    有了上面对Canvas 方法的认识,那么下面我就用上面的方法来进行相关练习

    /**
    * Created by yishujun on 16/6/3.
    */
    public class YView extends View {
        private Context mContext;
        //定义一个paint
        private Paint mPaint;
        public YView(Context context) {
            this(context, null);
        }
        public YView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
        public YView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.mContext = context;
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            drawNomal(canvas);
            drawTest(canvas);
            //drawDial(canvas);
        }
        /**
         * 常规绘制  以(0,0)作为坐标原点参考点
         * @param canvas
         */
        private void drawNomal(Canvas canvas){
           mPaint =new Paint();
            // 绘制画布背景
            canvas.drawColor(Color.GRAY);
            //设置画笔颜色
            mPaint.setColor(Color.BLUE);
            //设置画笔为空心     如果将这里改为Style.STROKE  这个图中的实线圆柱体就变成了空心的圆柱体
            mPaint.setStyle(Paint.Style.STROKE);
            //绘制直线
            canvas.drawLine(50, 50, 450, 50, mPaint);
            //绘制矩形
            canvas.drawRect(100, 100, 200, 300, mPaint);
            //绘制矩形
            mPaint.setStyle(Paint.Style.FILL);
            canvas.drawRect(300, 100, 400, 400, mPaint);
            mPaint.setColor(Color.YELLOW);
            RectF r = new RectF(150, 500, 270, 600);
            // 画矩形
            canvas.drawRect(r, mPaint);
            // 画圆
            canvas.drawCircle(50, 500, 50, mPaint);
            RectF oval = new RectF(350, 500, 450, 700);
            // 画椭圆
            canvas.drawOval(oval, mPaint);
            RectF rect = new RectF(100, 700, 170, 800);
            // 画圆角矩形
            canvas.drawRoundRect(rect, 30, 20, mPaint);
            //绘制圆弧 绘制弧形
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setColor(Color.RED);
            RectF re1 = new RectF(1000, 50, 1400, 200);
            canvas.drawArc(re1, 10, 270, false, mPaint);
            RectF re2 = new RectF(1000, 300, 1400, 500);
            canvas.drawArc(re2, 10, 270, true, mPaint);
            //设置Path路径
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(Color.GREEN);
            mPaint.setStrokeWidth(3);
            Path path = new Path();
            path.moveTo(500, 100);
            path.lineTo(920, 80);
            path.lineTo(720, 200);
            path.lineTo(600, 400);
            path.close();
            mPaint.setTextSize(46);
            canvas.drawPath(path, mPaint);
            canvas.drawTextOnPath("7qiuwoeruowoqjifasdkfjksjfiojio23ur8950", path, -20, -20, mPaint);
            //三角形
            path.moveTo(10, 330);
            path.lineTo(70, 330);
            path.lineTo(40, 270);
            path.close();
            canvas.drawPath(path, mPaint);
            //把开始的点和最后的点连接在一起,构成一个封闭梯形
            path.moveTo(10, 410);//绘画基点
            path.lineTo(70, 410);
            path.lineTo(55, 350);
            path.lineTo(25, 350);
            //如果是Style.FILL的话,不设置close,也没有区别,可是如果是STROKE模式, 如果不设置close,图形不封闭。当然,你也可以不设置close,再添加一条线,效果一样。
            path.close();
            canvas.drawPath(path, mPaint);
            //参数一为渐变起初点坐标x位置,参数二为y轴位置,参数三和四分辨对应渐变终点,其中参数new int[]{startColor, midleColor,endColor}是参与渐变效果的颜色集合,
            // 其中参数new float[]{0 , 0.5f, 1.0f}是定义每个颜色处于的渐变相对位置, 这个参数可以为null,如果为null表示所有的颜色按顺序均匀的分布
            // Shader.TileMode三种模式
            // REPEAT:沿着渐变方向循环重复
            // CLAMP:如果在预先定义的范围外画的话,就重复边界的颜色
            // MIRROR:与REPEAT一样都是循环重复,但这个会对称重复
            Shader mShader = new LinearGradient(0, 0, 100, 100,
                    new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW},
                    null, Shader.TileMode.REPEAT);
            mPaint.setShader(mShader);// 用Shader中定义定义的颜色来话
            mPaint.setStyle(Paint.Style.FILL);
            Path path1 = new Path();
            path1.moveTo(170, 410);
            path1.lineTo(230, 410);
            path1.lineTo(215, 350);
            path1.lineTo(185, 350);
            path1.close();
            canvas.drawPath(path1, mPaint);
            canvas.save();
        }

        /**
         * 绘制方法练习
         * @param canvas
         */
        private void drawTest(Canvas canvas){
            mPaint =new Paint();
            mPaint.setColor(Color.RED);
            //平移测试
            canvas.translate(50, 900);
            canvas.drawRect(new Rect(0, 0, 100, 100), mPaint);
            canvas.translate(50, 50);
            canvas.drawRect(new Rect(0, 0, 100, 100), mPaint);
            //缩放测试
            canvas.translate(100,-50);
            canvas.drawRect(new Rect(0, 0, 300, 300), mPaint);
            // 保存画布状态
            canvas.save();
            canvas.scale(0.5f, 0.5f);
            mPaint.setColor(Color.YELLOW);
            canvas.drawRect(new Rect(0, 0, 300, 300), mPaint);
            // 画布状态回滚
            canvas.restore();
            // 先将画布平移到矩形的中心
            canvas.translate(400, -50);
            canvas.drawRect(new Rect(0, 0, 300, 300), mPaint);
            //旋转测试
            canvas.save();
            canvas.translate(350, 50);
            canvas.drawRect(new Rect(0, 0, 200, 200), mPaint);
            mPaint.setColor(Color.RED);
            canvas.rotate(45,200,200);
            canvas.drawRect(new Rect(0, 0, 200, 200), mPaint);
            canvas.restore();
            //画布错切 三角函数tan的值
            canvas.translate(350, 300);
            canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
            // y 方向上倾斜45 度
            canvas.skew(0, 1);
            mPaint.setColor(0x8800ff00);
            canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
        }
    }

    示例截图

    {476F5900-10F4-A08F-2889-A4B10A8082FA}

    示例代码下载

  • 相关阅读:
    安装Spring Tool Suite(STS)
    ES6,新增数据结构Set的用法
    在vue-cli生成的项目中使用karma+chrome进行单元测试
    利用babel-cli搭建支持ES6的node环境
    利用es-checker检测当前node对ES6的支持情况
    javascript精度问题与调整
    sessionStorage 、localStorage、cookie
    在vue-cli搭建的项目中在后台mock接口中支持req.body和req.cookies
    wireshark抓取本地数据包
    【linux基础】How to write CMakeLists.txt file?
  • 原文地址:https://www.cnblogs.com/yishujun/p/5559917.html
Copyright © 2020-2023  润新知