转载请注明出处:http://blog.csdn.net/qinjuning    

因为在网络上找到关于Canvas的使用都比較抽象,或许是我的逻辑思维不太好吧,总是感觉理解起来比較困难,

尤其是对save()和restore()方法的使用。本篇文章的内容就是对Canvas的使用进行一下总结,包含它的两种不同的使用

情节和它的一些方法进行一下说明。

Bitmap,能够来自资源/文件,也能够在程序中创建,实际上的功能相当于图片的存储空间;


Canvas
,紧密与Bitmap联系,把Bitmap比喻内容的话,那么Canvas就是提供了众多方法操作Bitamp的平台;


Paint
,与Canvas紧密联系,是"画板"上的笔刷工具,也用于设置View控件上的样式;


Drawable
,假设说前三者是看不见地在内存中绘图(虚拟的),那么Drawable就是把前三者绘图结果表现出来的接口(真实的)。

Drawable多个子类,比如:位图(BitmapDrawable)、图形(ShapeDrawable)、图层(LayerDrawable)等。

以上引自于hellogv的《Android入门第十四篇之绘图》

我们打个简单的例如吧:

Paint        就是画笔

Bitmap    就是画布

Canvas   就是画家

于是,画家能够通过画笔能够在画布上进行不论什么的画画。

Canvas的两种使用情形,从Canvas对象的获得角度分析:

1、  自己定义View和自己定义SurfaceView中获得Canvas对象

因为自己定义View和SurfaceView在显示界面中已经获得了显示区域,canvas对象仅仅只是是在其显示(绘画)区域进行界面布局

的设计,当操作完成后,系统会显示canvas的操作结果。

自己定义View的画图方法为:

//存在canvas对象,即存在默认的显示区域
@Override
public void draw(Canvas canvas) {
//canvas画图
}

SurfaceView的画图方法为,比如:

           SurfaceView  surfaceView = new MySurfaceView() ;         //创建一个Surface对象
SurfaceHolder surfaceHolder = surfaceView. getHolder() ; //获得SurfaceHolder对象
Canvas canvas = surfaceHolder.lockCanvas() ; //获得canvas对象
//进行画图操作
surfaceHolder.unlockCanvasAndPost(canvas) ; //释放canvas锁,而且显示视图

2、  在其它情形下,我们须要通过代码创建一个Canvas对象,而且在绘画成功后,将该绘图区域转换为Drawable图片

或者通过setBitmap(bitmap)显现出来。一般步骤为:

   //创建一个的Bitmap对象 

      Bitmap bitmap = Bitmap.createBitmap(200, 100, Config.ARGB_8888) ;
//创建一个canvas对象,而且開始画图
Canvas canvas = new Canvas (bitmap) ; ImageView imgView = new ImageView(this) ; //或者其它能够设置背景图片的View控件 //为ImageView设置图像
//将Bitmap对象转换为Drawable图像资
Drawable drawable = new BitmapDrawable(bitmap) ;
imgView .setBackgroundDrawable(drawable) ; 或者简单点: imgView .setImageBitmap(bitmap);

这两种方式都能够显示我们的画图。

Canvas方法分析:

clipXXX()方法族

说明:在当前的绘图区域裁剪(clip)出一个新的绘图区域,这个绘图区域就是canvas对象的当前绘图区域了。

比如:clipRect(new Rect()),那么该矩形区域就是canvas的当前绘图区域了。

public int save()

说明:保存已经由canvas绘画出来的东西,在save()和restore()方法之间的操作不正确它们造成影响,比如旋转(roate)等。

并且对canvas的操作(roate和translate)都是暂时的,restore()后不再存在。

public voidrestore()

说明:复原sava()方法之前保存的东西资源。

drawXXX()方法族

说明:以一定的坐标值在当前绘图区域绘图。

注意:图层会叠加,即后面绘画的图层会覆盖前面绘画的图层。

须要注意的方法是:

public voiddrawRect(float left, float top, float right, float bottom,Paint
paint)

说明:绘制一个矩型。须要注明的是绘制矩形的參数和Java中的方法不一样。

该方法的參数图讲解明例如以下:

        各位看官请注意:图中X、Y轴方向标记错误。 自己也懒得又一次修正了。

 

那么,矩形的高 height = bottom  - right 

    矩形的宽 width  = right – left

PS :假如drawRect的參数有误,比方right < left ,Android是不会给我们检查的,也不会提示对应的错误信息,

但它会绘画出一个高或宽非常小的矩形,可能不是你希望的。

public voidtranslate(float dx, float dy)

说明:在当前的坐标上平移(x,y)个像素单位

若dx <0 ,沿x轴向上平移; dx >0  沿x轴向下平移

若dy <0 ,沿y轴向上平移; dy >0  沿y轴向下平移

public void
rotate
(float degrees)

说明:旋转一定的角度绘制图像。

PS :从截图上看,图像是确实旋转了,可是我找不到旋转的根据中心。

以下给出该Demo的截图,能够更改一些參数后自己观察效果。

  1、布局文件 main.xkl :  採用了两个ImageView来显示bitmap画图对象, 让后採用了一个自己定义View画图

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"> <View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="显示canvas区域以及clip方法的使用" /> <ImageView android:id="@+id/imgClip" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_marginTop="10dip" /> <View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="save方法和restore方法的使用" />
<ImageView android:id="@+id/imgSave" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_marginTop="10dip" /> <View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="自己定义View,获得了一个Canvas对象和画图区域" />
<com.qin.canvas.MyView android:id="@+id/myView"
android:layout_width="fill_parent" android:layout_height="200px" /> </LinearLayout>

    2、自己定义View  , MyView.java,

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.Bitmap.Config;
import android.util.AttributeSet;
import android.view.View; public class MyView extends View{ private Paint paint = new Paint() ; public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyView(Context context , AttributeSet attrs){
super(context,attrs);
}
//存在canvas对象,即存在默认的显示区域
@Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
super.draw(canvas);
//加粗
paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
paint.setColor(Color.BLUE);
canvas.drawText("自己定义View,canvas对象已经存在。", 30, 40, paint);
canvas.drawRect(10, 10, 30, 30, paint); //将icon图像转换为Bitmap对象
Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ;
canvas.drawBitmap(iconbit, 40,40, paint);
}
}

  3、主project文件 MainActivity.java

public class MainActivity extends Activity {
//画笔对象 paint
private Paint paint = new Paint() ; //记得要为paint设置颜色,否则 看不到效果
private ImageView imgClip ; // 画图区域以及clip方法
private ImageView imgSave ; // save方法以及restore /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main) ; imgClip = (ImageView)findViewById(R.id.imgClip) ;
imgSave = (ImageView)findViewById(R.id.imgSave); clip_drawCanvas() ; // 画图区域以及clip方法
save_drawCanvas(); // save方法以及restore
}
//这种情况下,须要创建Canvas对象,然后在此对象上进行操作
//对bitmap操作完毕后,,显示该Bitmap有下面两种操作。
//1、须要将bitmap转换为Drawable对象 Drawable drawable = new BitmapDrawable(bitmap) ;
//2、直接setImageBitmap(bitmap)
private void clip_drawCanvas(){
//将icon图像转换为Bitmap对象
Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ; //创建一个的Bitmap对象
Bitmap bitmap = Bitmap.createBitmap(200, 150, Config.ARGB_8888) ; Canvas canvas = new Canvas (bitmap) ;
//设置颜色来显示绘图区域
canvas.drawColor(Color.RED); paint.setColor(Color.BLACK);
canvas.drawText("原先的绘图区域--红色部分", 60,50,paint) ;
//画bitmap对象
canvas.drawBitmap(iconbit, 20, 20, paint); //剪裁一个区域,当前的操作对象为Rect裁剪的区域
Rect rect = new Rect (10,80,180,120) ; //当前的绘图区域为Rect裁剪的区域,而不是我们之前赋值的bitmap
canvas.clipRect(rect) ;
canvas.drawColor(Color.YELLOW);
//设置颜色来显示绘图区域
paint.setColor(Color.BLACK);
canvas.drawText("裁剪clip后绘图区域-黄色部分", 10,100,paint) ; //将Bitmap对象转换为Drawable图像资源
//Drawable drawable = new BitmapDrawable(bitmap) ;
//img.setBackgroundDrawable(drawable) ; //显示,同上
imgClip.setImageBitmap(bitmap);
} private void save_drawCanvas(){
//将icon图像转换为Bitmap对象
Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ; //创建一个的Bitmap对象
Bitmap bitmap = Bitmap.createBitmap(200, 100, Config.ARGB_8888) ; Canvas canvas = new Canvas (bitmap) ; paint.setColor(Color.GREEN);
paint.setTextSize(16); //设置字体大小
canvas.drawRect(10, 10, 50, 8, paint);
canvas.drawText("我没有旋转",50, 10, paint);
//保存canvas之前的操作,在sava()和restore之间的操作不会对canvas之前的操作进行影响
canvas.save() ; //顺时针旋转30度
canvas.rotate(30) ;
canvas.drawColor(Color.RED);
canvas.drawBitmap(iconbit, 20, 20, paint);
canvas.drawRect(50, 10, 80, 50, paint);
//canvas.translate(20,20);
canvas.drawText("我是旋转的",115,20, paint); //复原之前save()之前的属性,而且将save()方法之后的roate(),translate()以及clipXXX()方法的操作清空
canvas.restore(); //平移(20,20)个像素
//canvas.translate(20,20);
canvas.drawRect(80, 10, 110,30, paint);
canvas.drawText("我没有旋转",115,20, paint); //将Bitmap对象转换为Drawable图像资
//为ImageView设置图像
//imgSave.setImageBitmap(bitmap); Drawable drawable = new BitmapDrawable(bitmap) ;
imgSave.setBackgroundDrawable(drawable) ; }
}

总的来说,Canvas理解起来还是比較纠结的,尤其是它的几个方法真是让人头疼, 希望你可以自己编写对应的代码

理解透彻,才真正的有所收获。

Andriod中绘(画)图----Canvas的使用具体解释的更多相关文章

  1. Andriod中绘(画)图----Canvas的使用详解

    http://blog.csdn.net/qinjuning/article/details/6936783

  2. Canvas中如何画一条清晰的线宽为奇数(如1px逻辑像素)的线?

    我在开发中使用canvas的机会不是很多,但是第一次实际使用中就遇到了问题,"很久很久以前,我自己画了一个雷达图,线宽都是1像素,但是显示效果不如期望,这才发现canvas中的画线还是有坑的 ...

  3. html5 中的SVG 和canvas

    想到昨天看资料的时候,发现html5 中的SVG 和canvas 都可以表示图形,那它们到底有哪些区别呢?该如何正确的使用它们呢? 1.SVG:可缩放矢量图形,(Scalable Vector Gra ...

  4. Flutter中的绘图(Canvas&CustomPaint)API

    本文是Flutter中Canvas和CustomPaint API的使用实例. 首先看一下我们要实现的效果: 结合动图演示,列出最终目标如下: 在程序运行后,显示一个小球: 每次程序启动后,小球的样式 ...

  5. ASP.NET中数据棒图,饼图,柱状图的实现

    Web中绘制图形的方法大致有: 1. VML方式:功能强大,但是非常麻烦. 推荐:http://www.elook.net.cn/vml/ 2.使用控件:Dandus, Aspose.chart,Co ...

  6. 安卓图表引擎AChartEngine(四) - 源码示例 嵌入Acitivity中的折线图

    前面几篇博客中都是调用ChartFactory.get***Intent()方法,本节讲的内容调用ChartFactory.get***View()方法,这个方法调用的结果可以嵌入到任何一个Activ ...

  7. 软件工程 #02# Entity Relationship Diagram VS. 用 UML 中的类图表示 E-R 图

    不同的老师叫我们画 E-R 图居然是不一样的,于是我仔细研究了一番.. 通常所说的 E-R 图(外文全称 Entity Relationship Diagram,简称 ERD)长这个样子: 而有时候它 ...

  8. 简述WPF中的画刷(Brush)

    原文:简述WPF中的画刷(Brush) -------------------------------------------------------------------------------- ...

  9. MindManager中发送导图给别的用户的教程

    使用MindManager思维导图的过程中,可以发送当前导图.导图模版或导图主题给其他的Mindjet用户,如果正在进行导图审阅,发送导图时可以使用"供审阅"选项,本文具体为大家讲 ...

随机推荐

  1. HDU 4726 Kia's Calculation (贪心算法)

    Kia's Calculation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...

  2. Git本地分支版本号过低导致的push错误 error: failed to push some refs to ... 及兴许amend

    今天在用git的时候遇到了一个问题.在想远程分支push的时候,出现了以下的错误: ! [remote rejected] master -> refs/for/master (change 1 ...

  3. 【linux】linux内核移植错误记录

       欢迎转载,转载时请保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http ...

  4. Extjs实现树形结构三连选

    当项目中需要一个部门人员选择或者省市县地域连选时,就需要树形结构的连选. 再此,写了一个简单的树形结构三连选功能,模拟从后台读取数据和处理数据(欢迎大家交流指正). 代码如下: 循环创建三棵树,其中只 ...

  5. Spring Session - Spring Boot

    The completed guide can be found in the boot sample application. Updating Dependencies Before you us ...

  6. 在Centos 5.4上安装Mysql5.5.10 (整理以前的工作文档)

    1.     安装环境 1.1.  目的 安装Mysql5.5.10服务,提供公司XXXX测试环境.正式环境也采用该版本的mysql 1.2. 硬件环境 PC机:IntelE5300 内存4G 硬盘5 ...

  7. nginx的sendfile指令的作用

    linux为了解决对读文件产生的从应用空间到内核空间复制数据产生的效率影响引进了零拷贝.什么是零拷贝?这里就不多说了,请参考http://blog.csdn.net/crazyguang/articl ...

  8. 使用RNSwipeViewController类库进行视图切换

    如今很多应用已经不再局限于点击按钮触发事件来进行视图之间切换,为迎合给予用户更好体验,体现iOS系统极佳用户体验,使用手势来进行各个视图之间切换,用户至于一个大拇指在屏幕中央就可浏览到很多信息: 关于 ...

  9. centos 安装ganglia监控工具

    一个.ganglia基本介绍 ganglia它是一个分布式监控系统,那里有两个Daemon,每间:clientGangliaMonitoring Daemon (gmond)和服务端GangliaMe ...

  10. read table 时关键字TRANSPORTING NO FIELDS的用法

    关键字TRANSPORTING NO FIELDS 用于read table with key 一般用于等读取内表的时候,只是判断该内表中是否有次数据 不需要读取到工作区中. READ TABLE g ...