自定义控件基础知识--Canvas

来源:互联网 发布:知乎 日本研究生申请 编辑:程序博客网 时间:2024/06/15 20:28

Canvas(一)


一、今天我们就先通过下面两方面去了解

  • Canvas是什么,能干什么?
  • Canvasn怎么用

二、是什么?

Canvas时android图像处理最常用的一个类了,通俗的说叫画布,主要负责android中View的绘制工作,Canvas的获取方法有两种,一种时候通过View的onDraw(Canvas canvas)方法的参数中直接拿来使用,另一种则是直接new出来:
//第一种方式使用参数中的canvas@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //第二种方式(其中之一)    Bitmap bitmap = Bitmap.createBitmap(101,101, Bitmap.Config.RGB_565);    Canvas _canvas = new Canvas(bitmap);}

三、那么接下来我们看下Canvas各个方法的具体使用

1、设置画布背景颜色

canvas.drawColor(int color);

2、一个画圆的方法canvas.drawCircle();

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //设置画布背景颜色    canvas.drawColor(Color.YELLOW);    //设置画笔    mPaint.setColor(Color.RED);    mPaint.setStyle(Paint.Style.STROKE);    mPaint.setAntiAlias(true);    mPaint.setStrokeWidth(8);    //获取控件宽高    int height = getMeasuredHeight();    int width = getMeasuredWidth();    //计算圆的半径,对宽高进行判断,防止圆不完整    int radius = height > width ? width / 2 - 10 : height / 2 - 10;    /**    * 参数1:圆心的x坐标    * 参数2:圆心的Y坐标    * 参数3:圆的半径    * 参数4:画笔    * ps:坐标都是以控件的左上角为基准    */    canvas.drawCircle(width / 2, height / 2,radius,mPaint);}

3、接下来是画文字的canvas.drawText(...)这个方法是有多个重载方法的,下面就不一一介绍(原因往下看),介绍一个跟path有关的,因为这个比较炫一点

  • canvas.drawTextOnPath(...),看代码跟效果图,其实就是用Path控制文字的绘制路径
    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //设置画布背景颜色        canvas.drawColor(Color.YELLOW);        String str = "琛琛、仙仙、旺旺、基基几个二货!";        //创建画文字专用画笔        TextPaint paint = new TextPaint();        paint.setColor(Color.RED);        paint.setStyle(Paint.Style.FILL);        paint.setAntiAlias(true);        paint.setTextSize(48);        /**        * path的使用等后面深入点研究再单独记录        */        Path path = new Path();        path.rLineTo(0,300);        path.rLineTo(100,50);        path.rLineTo(200,300);        path.rLineTo(200,300);        /**        * 参数1:将要绘制的文字        * 参数2:文字绘制轨迹        * 参数3:x轴偏移量(没搞懂)        * 参数4:y轴偏移量(也没搞懂)        * 参数5:画笔        */        canvas.drawTextOnPath(str,path,0,0,paint);    }


4、其实上面不说canvas.drawText(...)是有原因的,因为我刚开始也兴冲冲的写了一大堆那个方法去画文字,结果发现,字数多了之后就懵逼了,换不了行,所以感觉没卵用,如果是画那种很少字,并比较固定的倒是可以考虑用下,找了下资料看,发现很多人都用StaticLayout来实现,查了下看TextView其实也是用这个实现的,下面简单的实现下看看!

    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //设置画布背景颜色        canvas.drawColor(Color.YELLOW);        String str = "琛琛、仙仙、旺旺、基基几个二货!一个带坏了一班人,一个约了几十次妹子吃饭手都没得拖,一个菊花黑完,最后一个就不说了,肥猪肉都不放过!";        //创建画文字专用画笔        TextPaint paint = new TextPaint();        paint.setColor(Color.RED);        paint.setStyle(Paint.Style.FILL);        paint.setAntiAlias(true);        paint.setTextSize(48);        /**        * 参数1:要画的文字        * 参数2:画笔        * 参数3:画多宽后换行(这个值理应用控件的宽跟padding等值进行计算,dome中偷懒写死了)        * 参数4:文字对其方式        * 参数5:试了下,应该是行高        * 参数6:试了下,应该是行间距        * 参数7:这个真没搞懂,以后知道了再说吧(尴尬)        */        StaticLayout layout = new StaticLayout(str,paint,300, Layout.Alignment.ALIGN_CENTER,1.0F,10.0F,true);        layout.draw(canvas);    }



5、使用canvas画线条,canvas.drawLine(...);这是画单条线条的,还有一个一次画多条线条的,canvas.drawLines(...),看事例:

  • canvas.drawLine(...),画线其实很好理解,两个点就能定义一条线,所以找到两个点,跟一支笔,加上画布(canvas)就妥妥的了 
    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //设置画布背景颜色        canvas.drawColor(Color.YELLOW);        //创建画笔(手续详细记录paint的使用)        Paint paint = new Paint();        paint.setColor(Color.RED);        paint.setStyle(Paint.Style.STROKE);        paint.setStrokeWidth(10.0f);        paint.setAntiAlias(true);        /**        * 参数1:起点的x坐标        * 参数2:起点的y坐标        * 参数3:终点的x坐标        * 参数4:终点的y坐标        * 参数5:画笔        * ps:这里其实就是在画布上画条对角线        */        canvas.drawLine(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);    }

  • canvas.drawLines(...),多条线条的绘制其实也不复杂,只会是把所有线条的点封装到了数组里面而已,下面看代码:
    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //设置画布背景颜色        canvas.drawColor(Color.YELLOW);        //创建画笔(后续详细记录paint的使用)        Paint paint = new Paint();        paint.setColor(Color.RED);        paint.setStyle(Paint.Style.STROKE);        paint.setStrokeWidth(10.0f);        paint.setAntiAlias(true);        /**        * 参数1:一个float数组,里面的元素按顺序往后,每四个点描述一条线,前两个描述线条起始点的x,y坐标,后两个点描述线条结束点的x,y坐标        * 如果出现剩下的元素不够四个点的,剩下的元素会被丢弃,下面例子中画了两条线条        *        * 参数2:画笔        */        canvas.drawLines(new float[]{20,50,getMeasuredWidth()-20,50,20,100,getMeasuredWidth()-20,100},paint);        //drawLines还有个重载方法,想用的可自行查阅文档,这里就不多说了    }

6、画椭圆canvas.drawOval(Rectf rectf,Paint paint),创建椭圆就要用到另一个东西,就是好RectF,这个东西表示的是一块区域,后续再深入点研究再做笔记

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //设置画布背景颜色    canvas.drawColor(Color.YELLOW);    //创建画笔(后续详细记录paint的使用)    Paint paint = new Paint();    paint.setColor(Color.RED);    paint.setStyle(Paint.Style.STROKE);    paint.setStrokeWidth(10.0f);    paint.setAntiAlias(true);    /**    * 参数1:椭圆的left值    * 参数2:椭圆的top值    * 参数3:椭圆的right值    * 参数4:椭圆的bottom值    */    RectF oval = new RectF(150, 200, 500, 400);    // 画一个椭圆    canvas.drawOval(oval, paint);}

为了便于理解元素在画布中的位置,下面是椭圆在控件中的位置示意图:


7、画弧度(扇形)canvas.drawArc(...),画弧分为两种方式,一种时候弧线的两端不跟中心点相连,这种就真的是弧,另外一种是跟中心点相连的,那就成扇形了,看代码并附上对比图:

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //设置画布背景颜色    canvas.drawColor(Color.YELLOW);    //创建画笔(后续详细记录paint的使用)    Paint paint = new Paint();    paint.setColor(Color.RED);    paint.setStyle(Paint.Style.STROKE);    paint.setStrokeWidth(10.0f);    paint.setAntiAlias(true);    /**    * 创建第一块区域    * 参数1:left    * 参数2:top    * 参数3:right    * 参数4:bottom    */    RectF oval = new RectF(100, 300, 300, 500);    /**    * 创建第二块区域(用于测试不连接圆心的)    */    RectF _oval = new RectF(500, 300, 700, 500);    /**    *  参数1:RectF对象。    *  参数2:开始的角度。(水平向右为0度顺时针反向为正方向)    *  参数3:扫过的角度    *  参数4:是否和中心连线    *  参数5:画笔    */    canvas.drawArc(oval, 0, 120, true, paint);    /**    * 弧线两端不连接圆心    */    canvas.drawArc(_oval, 0, 120, false, paint);}


8、画矩形canvas.drawRect(...),直接上代码:

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //设置画布背景颜色    canvas.drawColor(Color.YELLOW);    //创建画笔(后续详细记录paint的使用)    Paint paint = new Paint();    paint.setColor(Color.RED);    paint.setStyle(Paint.Style.STROKE);    paint.setStrokeWidth(10.0f);    paint.setAntiAlias(true);    /**     *  矩形区域     *  参数1:float left     *  参数2:float top     *  参数3:float right     *  参数4:float bottom     */     canvas.drawRect(100,100, 300, 300, paint);     //画圆角矩形     RectF _oval = new RectF(80, 260, 200, 300);     /**      * 参数1:矩形区域      * 参数2:圆角x轴方向半径      * 参数3:圆角y轴方向半径(第二第三个参数,可以把两个值调得相差大点,运行看效果就明白了)      * ps:矩形的圆角还可以通过设置paint的Join来实现,或许在Paint的笔记中详细说明      */     canvas.drawRoundRect(_oval, 10, 10, paint);  }

9、画多边形canvas.drawPath(Path path,Paint paint);,绘制多边形的原理其实是一个画线的过程,最后把线的点和终点连起来而已,所以这里就用到了一个绘制路径用的Path类,这类还木有时间深入研究,后续学习到了再补充笔记,下面看一个简单例子:

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //设置画布背景颜色    canvas.drawColor(Color.YELLOW);    //创建画笔(后续详细记录paint的使用)    Paint paint = new Paint();    paint.setColor(Color.RED);    paint.setStyle(Paint.Style.STROKE);    paint.setStrokeWidth(10.0f);    paint.setAntiAlias(true);    //创建一个path对象    Path path = new Path();    int width = getMeasuredWidth();    int height = getMeasuredHeight();    //初始化起始点,如果不初始化默认坐标为(0,0)    path.moveTo(width / 2, 0);    //五角星各个点的坐标(瞎猜的,不会算正规五角星的坐标)    path.lineTo(width-width/10, height-height/10);    path.lineTo(0,height/3);    path.lineTo(width,height/3);    path.lineTo(width/10,height-height/10);    //连接起点跟终点    path.close();    canvas.drawPath(path,paint);}


THE END!!!更高级的用户后续学习到了再补上,比如说错切、旋转等等!



注:由于个人android学习的大部分知识都来源于网络,比如说:郭霖、张鸿洋、泡在网上的日子等等大牛的博客,在此写下一些学习笔记,并加入一些个人的理解或者说总结,主要用于个人提升。

原创粉丝点击