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的博客以及慕课网的视频教程,相信肯定对你有帮忙!本人水平有限,如有错误,欢迎指出!









  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Android自定义View中的Canvas是一个绘图容器,可以在其上进行2D绘图操作。通过Canvas,我们可以绘制图形、文字、位图等。 要在自定义View中使用Canvas,需要重写View的onDraw()方法,并在该方法中获取Canvas实例,然后进行绘制操作。 下面是一个简单的示例代码,展示如何在自定义View中使用Canvas绘制一个矩形: ```java public class MyCustomView extends View { public MyCustomView(Context context) { super(context); } public MyCustomView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); canvas.drawRect(100, 100, 300, 300, paint); } } ``` 在这个示例中,我们创建了一个名为MyCustomView的自定义View,并重写了它的onDraw()方法。在该方法中,我们首先创建了一个Paint对象,设置了画笔的颜色为红色,并指定绘制的样式为填充。然后,使用Canvas的drawRect()方法绘制一个矩形,坐标为(100, 100)到(300, 300)。 当我们在布局文件中使用这个自定义View时,它会自动调用onDraw()方法进行绘制,从而在屏幕上显示出红色矩形。 需要注意的是,Canvas提供了许多其他绘制方法,如drawCircle()、drawText()等,可以根据需求选择合适的方法进行绘制操作。此外,还可以通过设置Paint对象的属性来实现不同的绘制效果,如线条宽度、字体大小等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值