图形绘制简介

  1.        Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0。大部分2D使用的api都在android.graphicsandroid.graphics.drawable包中。他们提供了图形处理相关的CanvasColorFilterPointRetcF等类,还有一些动画相关的AnimationDrawableBitmapDrawableTransitionDrawable等。
  2.       以图形处理来说,我们最常用到的就是在一个View上画一些图片、形状或者自定义的文本内容,这些都是使用Canvas来实现的。
  3.       另外,我们可以获取View中的Canvas对象,在绘制一些内容后调用View.invalidate方法让View重新刷新,然后再绘制一个新的内容,以此多次之后,就实现了2D动画的效果。

  4. 画图需要四大基本要素:
  5. 1、一个用来保存像素的Bitmap
  6. 2、一个或多个画笔Paint
  7. 3、需要绘制的内容
  8. 4、一个Canvas画布,用来在Bitmap上使用Paint绘制内容
  9.  

Canvas对象的获取方式

  1. Canvas对象的获取方式有三种:
  2. 1、通过重写View.onDraw方法获取Canvas对象。
  3. 这种方式根据环境还分为两种:一种是普通ViewCanvas,还有一种是SurfaceViewCanvas
  4. 两种的主要是区别就是,可以在SurfaceView中定义一个专门的线程来完成画图工作,应用程序不需要等待View的刷图,提高性能。
  5. 前面一种适合处理量比较小,帧率比较低的动画方面的绘图,比如说象棋游戏之类的;而后一种主要用在游戏或高品质动画方面的绘图。
  6. 2、直接创建一个Canvas对象:
  7. Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);  
  8. Canvas c = new Canvas(bitmap);
  9. 上面代码创建了一个尺寸是100*100Bitmap,使用它作为Canvas操作的对象,这时候的Canvas就是使用创建的方式。
    当你使用创建的Canvasbitmap上执行绘制方法后,你还可以将绘制的结果提交给另外一个Canvas,这样就可以达到两个Canvas协作完成的效果,简化逻辑。
  10.           但是android SDK建议使用View.onDraw参数里提供的Canvas就好,没必要自己创建一个新的Canvas对象。
  11. 3、调用SurfaceHolder.lockCanvas()也会返回一个Canvas对象,可以在 surfaceView TextureView中使用。
  12.  

Canvas位置装换、保存、恢复

  1.        Android还提供了一些对Canvas位置转换的方法:roratescaletranslateskew(扭曲)等,而且它允许你通过getMatrix获得它的转换矩阵对象,并可以直接操作它。这些操作就像是虽然你的笔还是在原来的地方画,但是画纸(坐标原点)旋转或者移动了,所以你画的东西的方位就产生了变化。
  2.       为了方便使用这些转换操作,Canvas 还提供了保存和回滚属性的方法saverestoresave用来保存Canvas的状态,save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。restore用来恢复Canvas之前保存的状态,防止save后对Canvas执行的操作对后续的绘制有影响。注意:saverestore要配对使用,如果restore调用次数比save多,会引发Error

  3. 小细节
  4. 上图,最初始的情况是栈里只有 0 1 2 3 4 ,然后执行 save 方法两次,则 5 6 出现在栈中
  5.  

Canvas可绘制的图形种类

  1. 1、绘制背景(填充)
  2.       drawARGB(int a, int r, int g, int b)
  3.       drawColor(int color)
  4.       drawRGB(int r, int g, int b)
  5.       drawColor(int color, PorterDuff.Mode mode)
  6. 2、绘制几何图形
  7.      canvas.drawArc (扇形,弓形,弧线区域)
  8.      canvas.drawCircle(圆)
  9.      canvas.drawOval(圆和椭圆)
  10.      canvas.drawLine(线)
  11.      canvas.drawPoint(点)
  12.      canvas.drawRect(矩形)
  13.      canvas.drawRoundRect(圆角矩形)
  14.      canvas.drawVertices(顶点)
  15.      cnavas.drawPath(路径,可用来绘制任意图形)
  16. 3、绘制图片
  17.        canvas.drawBitmap (位图)
  18.        canvas.drawPicture (图片)
  19. 4、绘制文本
  20.        canvas.drawText
  21.    
  22.  

Paint画笔工具相关设置

  1. Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色、样式等绘制信息,指定了如何绘制文本和图形。画笔对象有很多设置方法, 大体上可以分为两类:
  2. 1、图形相关的设置方法
    • setARGB(int a,int r,int g,int b); 设置绘制的颜色,a代表透明度,rgb代表颜色值。
    • setAlpha(int a); 设置绘制图形的透明度。
    • setColor(int color); 设置绘制的颜色,使用颜色值来表示,该颜色值包括透明度和RGB颜色。
    • setAntiAlias(boolean aa); 设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。
    • setDither(boolean dither); 设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
    • setFilterBitmap(boolean filter); 如果该项设置为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作,加快显示速度,本设置项依赖于ditherxfermode的设置
    • setMaskFilter(MaskFilter maskfilter); 设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等
    • setColorFilter(ColorFilter colorfilter); 设置颜色过滤器,可以在绘制颜色时实现不用颜色的变换效果
    • setPathEffect(PathEffect effect); 设置绘制路径的效果,如点画线等
    • setShader(Shader shader); 设置图像效果,使用Shader可以绘制出各种渐变效果
    • setShadowLayer(float radius ,float dx,float dy,int color); 在图形下面设置阴影层,产生阴影效果,radius为阴影的角度,dxdy为阴影在x轴和y轴上的距离,color为阴影的颜色
    • setStyle(Paint.Style style); 设置画笔的样式。FILL:实心,默认;FILL_OR_STROKE:填充并设置描边;STROKE:描边,空心
    • setStrokeCap(Paint.Cap cap); 定义线段断点形状。当画笔样式为STROKEFILL_OR_STROKE时,设置我们的画笔在【离开】画板时候留下的最后一点图形,如圆形样式 Cap.ROUND(有延长),或方形样式Cap.BUTT(默认,没有延长)与Cap.SQUARE(有延长)
    • setSrokeJoin(Paint.Join join); 设置绘制时各图形的结合方式(图形节点的样式),如平滑效果等
    • setStrokeWidth(float width); 当画笔样式为STROKEFILL_OR_STROKE时,设置笔刷的粗细
    • setXfermode(Xfermode xfermode); 设置图形重叠时的处理方式,如合并,取交集或并集
  3. 2.文本相关的设置方法
    • setFakeBoldText(boolean fakeBoldText); 模拟实现粗体文字,设置在小字体上效果会比较差
    • setSubpixelText(boolean subpixelText); 设置该项为true,将有助于文本在LCD屏幕上的显示效果
    • setTextAlign(Paint.Align align); 设置绘制文字的对齐方向
    • setTextScaleX(float scaleX); 设置绘制文字x轴的缩放比例,可以实现文字拉伸的效果
    • setTextSize(float textSize); 设置绘制文字的字号大小
    • setTextSkewX(float skewX); 设置斜体文字,skewXx轴方向的倾斜弧度
    • setTypeface(Typeface typeface); 设置字体风格,包括粗体,斜体以及衬线体,非衬线体等
    • setUnderlineText(boolean underlineText); 设置带有下划线的文字效果
    • setStrikeThruText(boolean strikeThruText); 设置带有删除线的效果
  4.  

代码-绘制各种图形

  1. public class TestPaintView extends View {
  2.     private Context context;
  3.     private Paint paint;
  4.     private RectF rect;//Rect是使用int类型作为数值,RectF是使用float类型作为数值
  5.     private Path path;//主要用于绘制复杂的图形轮廓,比如折线,圆弧以及各种复杂图案
  6.     private Bitmap bitmap;
  7.     private int left, top, right, bottom;

  8.     public TestPaintView(Context context) {
  9.         super(context);
  10.         this.context = context;
  11.         paint = new Paint();
  12.         rect = new RectF(0, 0, 0, 0);//左X、上Y、右X、下Y相应的距离,即左上角、右下角的坐标,系统不会检查数值的有效性
  13.         paint.setStrokeJoin(Paint.Join.ROUND);//设置绘制时图形的结合方式(图形节点的样式)
  14.         paint.setStrokeCap(Paint.Cap.ROUND);//设置画笔在【离开】画板时留下的最后一点的样式
  15.         paint.setAntiAlias(true);
  16.         paint.setDither(true);
  17.         paint.setStrokeWidth(dp2px(0.5f));//设置画笔粗细,单位为像素
  18.         bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
  19.     }

  20.     @SuppressLint("DrawAllocation")
  21.     @Override
  22.     protected void onDraw(Canvas canvas) {
  23.         //背景颜色
  24.         canvas.drawColor(0x33005500);
  25.         //矩形
  26.         initRect(10, 50, 10, 50);
  27.         paint.setStyle(Paint.Style.STROKE);//描边(空心),默认是FILL(实心、填充)
  28.         canvas.drawRect(rect, paint);
  29.         //绘制弧线区域(扇形或弓形)
  30.         paint.setStyle(Paint.Style.FILL);
  31.         paint.setColor(0xff00ff00);
  32.         canvas.drawArc(rect, 0, 90, false, paint);//当为false时是一个不经过【圆心】的弓形,当为true时是一个经过圆心的扇形
  33.         paint.setColor(0xffff0000);
  34.         canvas.drawArc(rect, 90, 150, true, paint); //圆弧所在矩形,起始角度90,旋转角度150,顺时针为正
  35.         //矩形内切圆(或椭圆)
  36.         paint.setStyle(Paint.Style.STROKE);
  37.         initRect(10, 30, 10, 50);
  38.         canvas.drawRect(rect, paint);
  39.         paint.setARGB(255, 0, 0, 255);
  40.         canvas.drawOval(rect, paint);
  41.         paint.setStyle(Paint.Style.FILL);
  42.         canvas.drawArc(rect, 0, 90, false, paint); //椭圆的扇形
  43.         paint.setARGB(128, 255, 0, 255);
  44.         canvas.drawArc(rect.left, rect.top, rect.right, rect.bottom, 90f, 150f, true, paint);

  45.         //圆角矩形
  46.         paint.setStyle(Paint.Style.STROKE);
  47.         initRect(10, 50, 10, 50);
  48.         canvas.drawRoundRect(rect, 20, 20, paint);//矩形,两侧圆角弧度的大小,一般都设为相同
  49.         //画直线
  50.         canvas.drawLine(dp2px(120), dp2px(25), dp2px(120), dp2px(55), paint);// 画一条线(首尾两点的坐标)
  51.         paint.setColor(Color.BLUE);
  52.         float[] points = new float[] { dp2px(120), dp2px(15), dp2px(150), dp2px(15),//画多条线。每条线都需要两个坐标(每两个值组成一个坐标)
  53.                 dp2px(130), dp2px(25), dp2px(150), dp2px(55), dp2px(150), dp2px(25) };
  54.         canvas.drawLines(points, paint);//最后两个值不够组成一条线,所以被废弃掉了。
  55.         paint.setColor(Color.BLACK);
  56.         canvas.drawLines(points, 2, 8, paint);//指定跳过前2个数据,取出8个数据绘制直线
  57.         // 画圆  
  58.         canvas.drawCircle(dp2px(190), dp2px(35), dp2px(25), paint);//圆心坐标,半径
  59.         //画点
  60.         paint.setStrokeWidth(dp2px(3));
  61.         canvas.drawPoint(dp2px(190), dp2px(35), paint);//画一个点
  62.         paint.setColor(Color.RED);
  63.         canvas.drawPoints(points, paint);//画多个点,每两个值组成一个坐标
  64.         //画图片,就是贴图  
  65.         canvas.drawBitmap(bitmap, dp2px(220), dp2px(10), paint);//坐标指的是左上角的位置
  66.         //canvas.drawCircle(320 + bitmap.getWidth() / 2, 200 + bitmap.getWidth() / 2, bitmap.getWidth() / 2, paint);
  67.         //*************************************************************************************

  68.         //画路径1,不规则封闭图形
  69.         paint.setStrokeWidth(dp2px(0.5f));
  70.         path = new Path();
  71.         path.moveTo(dp2px(10), dp2px(70));//指定初始轮廓点,若没指定默认从(0,0)点开始
  72.         path.lineTo(dp2px(10), dp2px(100));//从当前轮廓点绘制一条线段到指定轮廓点
  73.         path.lineTo(dp2px(50), dp2px(100));
  74.         path.lineTo(dp2px(50), dp2px(80));
  75.         path.close(); // 回到初始点形成封闭的曲线
  76.         canvas.drawPath(path, paint);
  77.         //画路径2,利用path也可以画各种图形,api使用上和canvas有些许区别
  78.         rect = new RectF(dp2px(60), dp2px(70), dp2px(110), dp2px(120));
  79.         path.addRect(rect, Direction.CW);//利用path画矩形。Diection.CW 顺时针方向,Diection.CCW 逆时针方向
  80.         canvas.drawPath(path, paint);
  81.         paint.setColor(Color.BLUE);//注意,同一path绘制的图形的颜色一定是相同的
  82.         Path path2 = new Path();//如果这里不重新new一个path,则前面用path绘制的图形的颜色也都会变
  83.         path2.addRoundRect(rect, new float[] { 20, 60, 20, 60, 60, 60, 20, 20 }, Direction.CW);//从左上角顺时针开始,四个角的x轴y轴方向的弧度
  84.         canvas.drawPath(path2, paint);
  85.         //绘制文本
  86.         canvas.drawLine(rect.left, rect.centerY(), rect.right, rect.centerY(), paint);
  87.         paint.reset();//重置
  88.         paint.setTextSize(dp2px(12));//单位是px,只在绘制文字时有效
  89.         paint.setTextAlign(Align.CENTER);//绘制的文字以drawText时指定的 float x 水平居中,默认值是Align.LEFT
  90.         canvas.drawText("1efg", rect.centerX(), rect.centerY(), paint);//注意 float y 代表的是 baseline 的值,也即e和f的下边界,而非g的下边界
  91.         paint.setUnderlineText(true);//带下划线
  92.         canvas.drawText("包青天efg", 0, "包青天efg".length(), rect.right + dp2px(30), rect.top + dp2px(12), paint);//(+textSize)可实现和矩形顶部对齐
  93.         canvas.drawText(new char[] { 'J', '!', '。', '.' }, 0, 4, rect.right + dp2px(30), rect.centerY(), paint);
  94.         //在指定路径上绘制文本
  95.         Path path3 = new Path();
  96.         path3.moveTo(rect.right, rect.bottom);
  97.         path3.lineTo(rect.right + dp2px(150), rect.centerY());
  98.         canvas.drawPath(path3, paint);
  99.         paint.setTextAlign(Align.LEFT);
  100.         canvas.drawTextOnPath("123456789", path3, 30, -10, paint);//float hOffset,相对基准线的向右偏移值, float vOffset向下偏移值
  101.     }

  102.     /**
  103.      * 重新设置矩形边界
  104.      * @param leftAdd, 代表新矩形的左边界距离上一个矩形的右边界的距离
  105.      * @param width,代表矩形的宽度
  106.      * @param topAdd, 代表新矩形的上边界的值
  107.      * @param hight,代表矩形的高度
  108.      */
  109.     private void initRect(int leftAdd, int width, int topValue, int hight) {
  110.         left = right + leftAdd;
  111.         right = left + width;
  112.         top = topValue;
  113.         bottom = top + hight;
  114.         rect.left = dp2px(left);
  115.         rect.right = dp2px(right);
  116.         rect.top = dp2px(top);
  117.         rect.bottom = dp2px(bottom);
  118.     }
  119.     private int dp2px(float dpValue) {
  120.         float scale = context.getResources().getDisplayMetrics().density;
  121.         return (int) (dpValue * scale + 0.5f);
  122.     }
  123. }
  124.  

代码-位置装换、保存、恢复

  1. public class TestCanvasView extends View {
  2.     private static final int SAVE_FLAGS = //Canvas.ALL_SAVE_FLAG //= 0x1F,还原所有,restore everything when restore() is called 
  3.     Canvas.MATRIX_SAVE_FLAG//= 0x01,需要还原Matrix。restore the current matrix when restore() is called 
  4.             | Canvas.CLIP_SAVE_FLAG //= 0x02,需要还原Clip。restore the current clip when restore() is called 
  5.             | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG //=0x04, 图层的 clip 标记。the layer needs to per-pixel alpha 
  6.             | Canvas.FULL_COLOR_LAYER_SAVE_FLAG//= 0x08,图层的 color 标记。the layer needs to 8-bits per color component
  7.             | Canvas.CLIP_TO_LAYER_SAVE_FLAG;// = 0x10,图层的 clip 标记,在saveLayer 和 saveLayerAlpha时Android强烈建议加上他
  8.     private Paint mPaint;
  9.     public TestCanvasView(Context context) {
  10.         super(context);
  11.         mPaint = new Paint();
  12.         mPaint.setAntiAlias(true);
  13.     }

  14.     @Override
  15.     protected void onDraw(Canvas canvas) {
  16.         super.onDraw(canvas);
  17.         canvas.drawColor(Color.WHITE);
  18.         //画一个红色的圆
  19.         mPaint.setColor(Color.RED);
  20.         canvas.drawCircle(100, 100, 100, mPaint);
  21.         canvas.save();//保存Canvas的状态,save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。save()默认保存的是matrix和clip
  22.         //画一个绿色的拉长的圆(即椭圆)
  23.         canvas.scale(0.5f, 1);//x、y轴的缩放比例
  24.         mPaint.setColor(Color.GREEN);
  25.         canvas.drawCircle(100, 100, 100, mPaint);
  26.         //画一个黄色的矩形
  27.         canvas.restore();//restore用来恢复Canvas之前保存的状态,防止save后对Canvas执行的指定操作对后续的绘制有影响
  28.         canvas.translate(200, 0);//把画布平移。此操作对下面新建的那个图层依然是有效的
  29.         mPaint.setColor(Color.YELLOW);
  30.         canvas.drawRect(0, 0, 200, 200, mPaint);
  31.         canvas.save(SAVE_FLAGS);//指定哪些需要还原。只有指定matrix或clip才有效,其余几个参数在saveLayer和saveLayerAlpha方法中才有效

  32.         //画一个蓝色的扭曲的矩形
  33.         canvas.skew(2f, 1);//图形变换唯一规则:将x坐标全部变为*2,将y坐标全部变为*1。至于是否平行啦之类的都不去限制。
  34.         mPaint.setColor(Color.BLUE);
  35.         canvas.drawRect(0, 0, 100, 100, mPaint);
  36.         //画一个带透明度的蓝色的旋转的小矩形
  37.         canvas.restore();//取消扭曲。
  38.         canvas.translate(200, 0);
  39.         canvas.rotate(30, 50, 50);//沿指定点为中心顺时针旋转指定角度。默认是以左上角为中心
  40.         int count = canvas.saveLayerAlpha(0, 0, 200, 200, 0x88, SAVE_FLAGS);//在指定边界新建一个透明度为0x88的图层
  41.         canvas.drawRect(0, 0, 100, 100, mPaint);//绘制时使用的颜色仍是上次的蓝色,而非save之前的颜色。这个图层的透明度对此图形是有影响的
  42.         //画一个绿色的小圆
  43.         canvas.restore();
  44.         canvas.restore();//如果restore调用的次数大于save的调用次数,会出错。
  45.         canvas.restoreToCount(count);
  46.         mPaint.setColor(Color.GREEN);
  47.         canvas.drawCircle(50, 50, 50, mPaint);// 这个圆是在原来的图层上划的, 没有透明度
  48.     }
  49. }
  50.  

图形绘制 Canvas Paint Path 详解的更多相关文章

  1. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  2. canvas绘图API详解

    canvas绘图API详解 1.context的状态 矩阵变换属性 当前剪辑区域 context的其他状态属性: strokeStyle, fillStyle, globalAlpha, lineWi ...

  3. canvas arcTo()用法详解 – CodePlayer

    canvas arcTo()用法详解 – CodePlayer canvas arcTo()用法详解

  4. Eclipse Java Build Path详解

    Eclipse Java Build Path详解 1.设置"source folder"与"output folder". * source folder:存 ...

  5. Python绘制六种可视化图表详解,三维图最炫酷!你觉得呢?

    Python绘制六种可视化图表详解,三维图最炫酷!你觉得呢? 可视化图表,有相当多种,但常见的也就下面几种,其他比较复杂一点,大都也是基于如下几种进行组合,变换出来的.对于初学者来说,很容易被这官网上 ...

  6. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  7. 第157天:canvas基础知识详解

    目录 一.canvas简介 1.1 什么是canvas?(了解) 1.2 canvas主要应用的领域(了解) 二.canvas绘图基础 2.0 sublime配置canvas插件(推荐) 2.1 Ca ...

  8. canvas arcTo()用法详解

    CanvasRenderingContext2D对象的方法arcTo()的用法. arcTo(x1, y1, x2, y2, radius) arcTo()方法将利用当前端点.端点1(x1,y1)和端 ...

  9. canvas径向渐变详解

    创建径向渐变步骤如下: 1,创建径向渐变对象 createRadialGradient(x0,y0,r0,x1,y1,r1),其中x0,y0,r0分别为起始圆的位置坐标和半径,x1,y1,r1为终止圆 ...

随机推荐

  1. SQL server概述

    sqlserver中包含的对象: 数据库.事务日志.索引.文件组.数据库关系图.视图.存储过程.用户自定义函数.用户.角色.程序集.表.报表.全文目录.用户自定义数据类型 数据库实际上是最高层对象,其 ...

  2. asp.net能不托管吗?

    弱弱地问一句,整个部署在IIS中的asp.net项目能不托管吗? 或者说有没有用纯粹的非托管语言(比方说C语言)写的非托管asp.net项目?

  3. 让一个Activity在开机后自动显示

    Activity本身不会在手机开机后自动运行的.但想让手机开机后就立刻做一些动作,需要使用广播接收器拦截手机开启广播,并在onReceive方法中完成相应的动作,如打开一个Activity. 广播接收 ...

  4. c#播放声音文件

    C#中声音的播放主要有三种方法: 1.使用API函数. 2.使用SoundPlayer类播放. 3.使用DirectX进行播放. 一.使用API函数进行播放. windows操作系统中的winmm.d ...

  5. jdbc接口api

    java.sql.* 和 javax.sql.* |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接口. |- connect(url, properties): ...

  6. acdream暴力专场中的优美暴力

    F - 小晴天老师系列——苹果大丰收 Time Limit: 2000/1000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/Other ...

  7. 安卓4.2原生rom状态栏显示运营商

    前言:要调整状态栏布局,需反编译systemui.apk.单卡机修改status_bar.xml和signal_cluster_view.xml,双卡机修改gemini_status_bar.xml和 ...

  8. Top 100 English Verbs

    accept allow ask believe borrow break bring buy can/be able cancel change clean comb complain cough ...

  9. ural 1052 Rabbit Hunt

    http://acm.timus.ru/problem.aspx?space=1&num=1052 #include <cstdio> #include <cstring&g ...

  10. Leetcode:Largest Number详细题解

    题目 Given a list of non negative integers, arrange them such that they form the largest number. For e ...