Android 绘图(二) Canvas

上篇文章,我们讲述了Paint(画笔)类的。如果你还未了解,那么可以先看看这篇文章,Android 绘图(一) Paint。今天这篇文章,我们来看看Canvas。Canvas 是画布,来响应绘画(Draw)的调用(并将其写入Btmap)。

我们先看看官方文档对Canvas的描述:

The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels,
a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap),
and a paint (to describe the colors and styles for the drawing). 

简单翻译:Canvas 类持有Draw的调用。绘图的时候,你需要4个基本的组件:一个包含像素的Btmap(位图),一个Canvas
提供Draw调用(写入到Btmap中),一个图元(如矩形、路径、文本、位图),和一个画笔(用来描述颜色和样式为绘图)。

Canvas类,前面已经简单描述过。绘制的时候,需要用画笔(Paint)在画布(Canvas)上面绘画(Draw)。

一. 下面列举一些 Canvas(画布)常用的绘制方法,

1 public void drawArc (float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
参数
  startAngle 	弧的开始的起始角(度)
  sweepAngle 	顺时针测量的弧度(度)
  useCenter 	如果是真,包含圆弧的中心和如果它是描边将关闭。这将是一个楔形。
  paint 	绘制弧形的画笔
绘制指定的弧形,该圆弧将按比例缩小到指定的椭圆内。
2 public void drawCircle (float cx, float cy, float radius, Paint paint)
参数
  cx 	绘制的圆中心的x坐标
  cy 	绘制的圆中心的y坐标
  radius 绘制的圆半径
  paint  绘制圆的画笔
绘制指定圆使用指定的画笔。如果半径小于等于0,什么都不绘制。圆将被填满或者描线基于画笔的样式。
3 public void drawLine (float startX, float startY, float stopX, float stopY, Paint paint)
参数
  startX  线起始点的x坐标
  startY  线起始点的y坐标
  paint   绘制线的画笔
绘制一条线段使用指定的起点、终点,x,y坐标,使用指定的画笔。注意,一条线默认是实线,所以画笔的样式被忽略。退化线(长度为0)将不是绘制。
4 public void drawOval (float left, float top, float right, float bottom, Paint paint)
绘制指定的椭圆使用指定的画笔。椭圆将被填充或者描线基于画笔的样式。
5 public void drawRGB (int r, int g, int b)
参数
  r 	 在画布上绘制的红色色值,取值范围(0..255).
  g 	 在画布上绘制的绿色色值,取值范围(0..255).
  b 	 在画布上绘制的蓝色色值,取值范围(0..255).
填充全部的画布的位图(限于当前剪辑)使用指定的RGB颜色。
6 public void drawRect (float left, float top, float right, float bottom, Paint paint)
参数
  left 	  要绘制的矩形的左边
  top 	  要绘制的矩形的上边
  right   要绘制的矩形的右边
  bottom  要绘制的矩形的下边
  paint   绘制区域的使用的画笔
在指定的区域绘制使用指定的画笔。矩形将被填充或者描边基于画笔的样式。
7 public void drawRect (RectF rect, Paint paint)
参数
  rect    绘制的区域
  paint   绘制矩形的画笔
在指定的区域绘制使用指定的画笔。矩形将被填充或者描边基于画笔的样式。
8 public void drawRect (Rect r, Paint paint)
参数
  r 	 绘制的矩形
  paint  绘制矩形的画笔
在指定的区域绘制使用指定的画笔。矩形将被填充或者描边基于画笔的样式。

ps:

1. RectF类。

RectF holds four float coordinates for a rectangle. The rectangle is represented by the coordinates of its 4 edges (left, top, right bottom). These fields can be accessed directly.
Use width() and height() to retrieve the rectangle‘s width and height. Note: most methods do not check to see that the coordinates are sorted correctly (i.e. left <= right and top <= bottom).

RectF 这个类包含一个矩形的四个单精度浮点坐标。矩形通过上下左右4个边的坐标来表示一个矩形。这些坐标值属性可以被直接访问,用width()和 height()方法可以获取矩形的宽和高。注意:大多数方法不会检查这些坐标分类是否错误(也就是left<=right和top<=bottom).

RectF一共有四个构造方法:

RectF()构造一个无参的矩形

RectF(float left,float top,float right,float bottom)构造一个指定了4个参数的矩形

RectF(Rect F r)根据指定的RectF对象来构造一个RectF对象(对象的左边坐标不变)

RectF(Rect r)根据给定的Rect对象来构造一个RectF对象

2. Rect类。

Rect holds four integer coordinates for a rectangle. The rectangle is represented by the coordinates of its 4 edges (left, top, right bottom). These fields can be accessed directly.
Use width() and height() to retrieve the rectangle‘s width and height. Note: most methods do not check to see that the coordinates are sorted correctly (i.e. left <= right and top <= bottom).

Rect 这个类包含一个矩形的四个整形坐标。矩形通过上下左右4个边的坐标来表示一个矩形。这些坐标值属性可以被直接访问,用width()和 height()方法可以获取矩形的宽和高。注意:大多数方法不会检查这些坐标分类是否错误(也就是left<=right和top<=bottom).

3. 二者的区别。

Rect类,这个类同RectF类很相似,不同的地方是Rect类的坐标是用整形表示的,而RectF类的坐标是用单精度浮点型表示的。

9  public void drawText (String text, float x, float y, Paint paint)
参数
  text 	绘制的文本
  x 	绘制文本的原点的x坐标
  y 	绘制文本的基线的y坐标
  paint 用于绘制文本的画笔。(例如颜色、大小、样式)
绘制文本,原点坐标(x,y),使用指定的画笔。原点显示是基于画笔设置的对齐方式。
10 public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)
参数
  bitmap  绘制位图
  matrix  绘制位图时使用的矩阵
  paint   可能为控制。绘制位图使用的画笔
使用指定的矩阵绘制位图
11 public boolean clipPath (Path path)
参数
  path 	与当前剪辑相交的路径
返回值
  如果返回真,表示结果非空
指定的路径与当前剪辑相交
12 public boolean clipRect (Rect rect, Region.Op op)
参数
  rect 	与当前剪辑相交的矩形
  op 	   如何剪辑
返回值
  如果返回真,表示剪辑结果非空
修建当前剪辑和指定的矩形,在局部坐标中表示。
13 public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)
参数
 bitmap  绘制的位图
 matrix  当绘制位图时需要转变时使用的矩阵
 paint 	 可能为空.绘制位图的画笔.
使用指定的矩阵绘制位图

14 public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)
参数
 bitmap  绘制的位图
 left  开始绘制位图时的左侧位置
 top  开始绘制位图时的上面位置
 paint  可能为空.绘制位图的画笔
绘制指定的位图,它的上/左包含在内,使用指定的画笔,通过当前矩阵变换。

15 public void translate (float dx, float dy)
参数
  dx 	x轴移动的距离
  dy 	y轴移动的距离
画布平移。基于上次移动后的点为原点。初始值原点坐标为(0,0)

例子:画布原点假如落在(0,0),那么translate(10,10)就是在原点(0,0)基础上分别在x轴、y轴移动10,则原点变为(10,10),再次调用translate(10,10),那么原点变为(20,20)。

16 public int save ()
返回值
    The value to pass to restoreToCount() to balance this save()
    该值传递到restoreToCount()中权衡save()
保存当前的矩阵和切片到一个私有的栈中。随后调用平移、缩放、旋转、倾斜、连接或者剪辑,都将照常操作,但是当调用restore()后,所有的都将被遗弃,恢复到save()之前存在的状态。
17 public void restore ()
恢复画布到save()之前的状态

ps:当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响。

18 public void scale (float sx, float sy)
参数
sx 	X缩放的数值
sy 	Y缩放的数值
使用当前矩阵对画布进行缩放
19 public final void scale (float sx, float sy, float px, float py)
参数
sx 	X缩放的数值
sy 	Y缩放的数值
px 	中心点的x坐标(未缩放)
py 	中心点的y坐标(未缩放)
使用当前矩阵对画布进行缩放

ps:从源码上可以非常清楚的看出scale (float sx, float sy, float px, float py)和scale(float sx , float sy)的差别:

public final void scale(float sx, float sy, float px, float py) {

translate(px, py);

scale(sx, sy);

translate(-px, -py);

}

即先将画布平移px,py,然后scale,scale结束之后再将画布平移回原基准点。

以上就是Canvas (画布)的常用Api,说了这么多,可能还是有些抽象,下面,我们通过实际的例子来演示方法。

二. 例子。

1.新建Android项目。

2.自定义View。

public class View1 extends View {

	private Paint mPaint = new Paint();
	private int DEFAULT_STROKE_WIDTH = 10;// strokeWidth
	private int DEFAULT_RADIUS = 30;// 半径
	private int DEFAULT_TEXT_SIZE = 20;//

	private int mStrokeWidth = dp2px(DEFAULT_STROKE_WIDTH);
	private int mRadius = dp2px(DEFAULT_RADIUS);
	private int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
	RectF rect;// 矩形

	public View1(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}

	public View1(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}

	public View1(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		// 绘制一条线段
		mPaint.setColor(Color.RED);// 设置画笔颜色为白色
		mPaint.setAntiAlias(true);// 坑锯齿
		mPaint.setStrokeWidth(mStrokeWidth);// 设置画笔的宽度
		canvas.drawLine(0, 0, 400, 0, mPaint);// 绘制一条线段
		// 绘制空心圆
		mPaint.setColor(Color.GRAY);// 设置画笔颜色为蓝色
		mPaint.setAntiAlias(true);// 坑锯齿
		mPaint.setStyle(Style.STROKE);// 样式是描边
		canvas.drawCircle(100, 100, mRadius, mPaint);// 绘制圆
		// 绘制矩形
		mPaint.setColor(Color.GREEN);// 设置画笔颜色为绿色
		mPaint.setStyle(Style.FILL);// 样式是填充
		rect = new RectF(200, 200, 300, 300);// 初始化矩形
		canvas.drawRect(rect, mPaint);
		Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.setting);
		canvas.drawBitmap(bitmap, 400, 400, mPaint);

		// 绘制文字
		mPaint.setColor(Color.BLACK);// 设置画笔颜色为绿色
		mPaint.setTextSize(mTextSize);// 设置画笔文字的大小
		canvas.drawText("50", 100, 500, mPaint);// 绘制文字
	}

	/**
	 * @param dpVal
	 * @return
	 */
	private int dp2px(int dpVal) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
				dpVal, getResources().getDisplayMetrics());
	}

	/**
	 * @param spVal
	 * @return
	 */
	private int sp2px(int spVal) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
				spVal, getResources().getDisplayMetrics());
	}
}

效果截图,如下所示,

3.自定义View,展示画布平移。

public class View3 extends View {
	private Paint mPaint = new Paint();
	private int DEFAULT_STROKE_WIDTH = 10;// strokeWidth
	private int DEFAULT_RADIUS = 30;// 半径
	private int DEFAULT_TEXT_SIZE=20;//
	private int mStrokeWidth = dp2px(DEFAULT_STROKE_WIDTH);
	private int mRadius = dp2px(DEFAULT_RADIUS);
	private int mTextSize=sp2px(DEFAULT_TEXT_SIZE);
	RectF rect;// 矩形
	public View2(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}
	public View2(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}
	public View2(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
	}
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		// 绘制一条线段
		mPaint.setColor(Color.RED);// 设置画笔颜色为白色
		mPaint.setAntiAlias(true);// 坑锯齿
		mPaint.setStrokeWidth(mStrokeWidth);// 设置画笔的宽度
		rect = new RectF(0, 0, 200, 200);//初始化矩形
		canvas.drawRect(rect, mPaint);
		canvas.translate(50, 50);
		mPaint.setColor(Color.BLACK);// 设置画笔颜色为白色
		canvas.drawRect(rect, mPaint);
		canvas.translate(50, 50);
		mPaint.setColor(Color.BLUE);// 设置画笔颜色为白色
		canvas.drawRect(rect, mPaint);
	}
	/**
	 * @param dpVal
	 * @return
	 */
	private int dp2px(int dpVal) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
				dpVal, getResources().getDisplayMetrics());
	}
	/**
	 * @param spVal
	 * @return
	 */
	private int sp2px(int spVal) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
				spVal, getResources().getDisplayMetrics());
	}
}

效果截图,

可以看出,每次调用平移后,都是在上次平移后叠加的!

4.自定义View,展示画布缩放。

public class View3 extends View {
	private Paint mPaint = new Paint();// 画笔
	private int DEFAULT_STROKE_WIDTH = 10;// strokeWidth
	private int mStrokeWidth = dp2px(DEFAULT_STROKE_WIDTH);
	private int TOTAL_SQUARE_COUNT = 20;// 矩形个数
	private int mWidth = 0;// 宽度
	private int mHalfWidth = 0;// 宽度一半
	RectF rect;// 矩形
	public View3(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}
	public View3(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}
	public View3(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
		setBackgroundColor(Color.BLACK);// 设置背景色
	}
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub

		mWidth = getMeasuredWidth();// 获取宽度
		mHalfWidth = mWidth / 2;//
		mPaint.setColor(Color.RED);// 设置画笔颜色为白色
		mPaint.setAntiAlias(true);// 坑锯齿
		mPaint.setStyle(Style.STROKE);// 样式是描边
		mPaint.setStrokeWidth(mStrokeWidth);// 设置画笔的宽度
		rect = new RectF(0, 0, mWidth, mWidth);//初始化矩形
		drawSquare(canvas);
	}
	/**
	 * 绘制图案
	 *
	 * @param canvas
	 */
	private void drawSquare(Canvas canvas) {
		for (int i = 0; i < TOTAL_SQUARE_COUNT; i++) {
			canvas.save();
			float fraction = (float) i / TOTAL_SQUARE_COUNT;
			canvas.scale(fraction, fraction, mHalfWidth, mHalfWidth);
			canvas.drawRect(rect, mPaint);
			canvas.restore();
		}
	}
	/**
	 * @param dpVal
	 * @return
	 */
	private int dp2px(int dpVal) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
				dpVal, getResources().getDisplayMetrics());
	}
	/**
	 * @param spVal
	 * @return
	 */
	private int sp2px(int spVal) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
				spVal, getResources().getDisplayMetrics());
	}
}

效果截图如下,

调用scale (float sx, float sy, float px, float py),某一个图形按照某一个缩放比例缩放。

三. 总结。

相信大家在自定义View中,或多或少都会见到上述Canvas(画布)Api的调用。如果你对自定义View有所顾虑、担心,推荐看看Hongyang的博客以及慕课网的视频教程,相信肯定对你有帮忙!本人水平有限,如有错误,欢迎指出!

时间: 2024-10-24 21:02:11

Android 绘图(二) Canvas的相关文章

android 绘图之Canvas,Paint类

Canvas,Paint 1.在android 绘图但中经常要用到Canvas和Paint类,Canvas好比是一张画布,上面已经有你想绘制图画的轮廓了,而Paint就好比是画笔,就要给Canvas进行添色等操作. 这两个类通常都是在onDraw(Canvas canvas)方法中用的. 2.Bitmap:代表一张位图,BitmapDrawable里封装的突变就是一个Bitmao对象 3.Canvas里面有一些例如: drawArc(参数) 绘制弧 drawBitmao(Bitmap bitma

Android笔记二十八.Android绘图深度解析

Android绘图深度解析 转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空) Android绘图方法主要有两个步骤: (1)实现一个继承于View组件的类,并重写它的onDraw(Canavas canvas)方法; (2)显示定义的View子类,有两种方法:a.使用一个Activity来显示View子类,即 setContentView(new MyView(this, null));b.在Acitviy的布局文件中增加"包名.View子类&

Android 绘图之一:Canvas 及 Paint 简介

前言 除了使用已有的图片之外,Android应用常常需要在运行时根据场景动态生成2D图片,比如手机游戏,这就需要借助于Android2D绘图的支持.本篇博客主要讲解一下Android下使用Canvas进行绘图的相关操作.最后将以一个简单的Demo演示如何使用Canvas在ImageView上画图并保存. 画布Canvas 在Android下进行2D绘图需要Canvas类的支持,它位于"android.graphics.Canvas"包下,直译过来为画布的意思,用于完成在View上的绘图

Android绘图

Android绘图方法主要有两个步骤: (1)实现一个继承于View组件的类,并重写它的onDraw(Canavas canvas)方法; (2)显示定义的View子类,有两种方法:a.使用一个Activity来显示View子类,即 setContentView(new MyView(this, null));b.在Acitviy的布局文件中增加"包名.View子类"元素,Activiyty通过setContentView方法来使用该布局文件.下面我们来学习下Android绘制图形的三

Android 绘图(一) Paint

了解Android绘图或者自定义View的同学,都知道Canvas 类.Paint类等.今天就来看看Paint的有关描述. 首先看看官网的定义: The Paint class holds the style and color information about how to draw geometries, text and bitmaps. 翻译:Paint类拥有如何绘制几何图形.文本.位图的颜色和样式等信息. Android系统提供了设置画笔属性的Api,接下来,就来看一些常用Api的使

Android绘图那些事儿(上)

(一)概述 虽然,已经学过了Android绘图的内容,但是总是觉得很模糊,今天就好好梳理下思路吧!纯粹就是一个读书笔记,整理下自己以前不知道的内容,好了开始:(本节主要介绍一些Drawable的常用方法及其xml定义,如果你已经很熟悉了,就跳过吧) (二)Android屏幕适配问题 Android屏幕适配和兼容,一直都是非常头疼的问题,如何才能在不同的屏幕尺寸的手机上图片效果显示不失真!现在看看屏幕这个渣渣的相关参数吧: NO.1----屏幕相关的参数 1)屏幕大小 指的是屏幕对角线的长度,通常

Android绘图机制与处理技巧

一屏幕的尺寸信息 1屏幕参数 2系统屏幕密度 3独立像素密度dp 4单位换算 二2D绘图基础 三Android XML 绘图 Bitmap Shape Layer Selector 四绘图技巧 Canvas 一.屏幕的尺寸信息 1屏幕参数 屏幕大小 指屏幕对角线的长度,通常使用"寸"来度量,例如4.7寸手机 5.5寸手机等. 分辨率 分辨率是指手机屏幕的像素点个数,例如720*1280是指屏幕分变率,指宽有720个像素点,高有1280个像素点. PPI 每英寸像素(Pixels Per

Android群英传知识点回顾——第六章:Android绘图机制与处理技巧

6.1 屏幕的尺寸信息 6.1.1 屏幕参数 6.1.2 系统屏幕密度 6.1.3 独立像素密度dp 6.1.4 单位转换 6.2 2D绘图基础 6.3 Android XML绘图 6.3.1 Bitmap 6.3.2 Shape 6.3.3 Layer 6.3.4 Selector 6.4 Android绘图技巧 6.4.1 Canvas 6.4.2 Layer图层 6.5 Android图像处理之色彩特效处理 6.5.1 色彩矩阵分析 6.5.2 Android颜色矩阵--ColorMatr

第三章 Android绘图机制与处理技巧

1.屏幕尺寸信息 屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DPI(Dots Per Inch),它是对角线的像素点数除以屏幕大小得到的:系统屏幕密度:android系统定义了几个标准的DPI值作为手机的固定DPI.(注,最后一个有笔误,正确的是1080x1920)独立像素密度(DP):android系统使用mdpi屏幕作为标准,在这个屏幕上1dp=1px,其他屏幕可以通过比例进行换算.在hdpi中,