在Android项目开发中,很多时候自带的View不能满足我们的需要,而需要我们继续View类或其子类去实现我们的自定义View。不管是Android,还是HTML5,绘制View都用了一个画布(Canvas)的概念。下面先上一段我写的测试代码,再分析要点。

public class CocoView extends View {private static final String tag = "CocoView";private Paint rectPaint = new Paint();private Paint circlePaint = new Paint();private Paint linePaint = new Paint();private Paint pathPaint = new Paint();private Paint textPaint = new Paint();public CocoView(Context context) {super(context);initCocoView();}public CocoView(Context context, AttributeSet attrs) {super(context, attrs);initCocoView();}private void initCocoView() {rectPaint.setColor(getResources().getColor(R.color.color1));linePaint.setStrokeWidth(3);circlePaint.setColor(getResources().getColor(R.color.color2));circlePaint.setAntiAlias(true);circlePaint.setAlpha(120);linePaint.setColor(getResources().getColor(R.color.color3));linePaint.setStrokeWidth(6);pathPaint.setColor(getResources().getColor(R.color.color4));pathPaint.setStyle(Style.STROKE); // 还有FILL, FILL_AND_STROKEpathPaint.setStrokeWidth(3);textPaint.setColor(Color.BLACK);textPaint.setTextSize(28);}@Overrideprotected void onDraw(Canvas canvas) {Log.e(tag, "onDraw : " + getMeasuredWidth() + ", " + getMeasuredHeight());// 1.绘颜色canvas.drawColor(Color.WHITE);// 2.绘矩形canvas.drawRect(100, 100, 300, 300, rectPaint);canvas.save();// 设置只在指定范围内绘制(即下面的绘制只在这个范围内的部分才可见),注意:1、坐标还是按View的坐标;2、不会影响前面已经绘制的;3、加save()和restore()块,是为了不影响restore()后面绘制canvas.clipRect(200, 200, 350, 350);// 3.绘圆形canvas.drawCircle(300, 300, 100, circlePaint);canvas.restore();// 4.绘线条canvas.drawLine(0, 0, 300, 300, linePaint);// 5.绘路径、不规则图形Path path = new Path();path.moveTo(50, 50);path.lineTo(300, 50);path.lineTo(50, 300);path.close();canvas.drawPath(path, pathPaint);canvas.save();canvas.translate(50, 50); // 画布移动,注意:默认的画布是与View的坐标对齐的,移动后就会与View的坐标产生偏移,而下面绘制的坐标将是基于移动后的画布canvas.scale(0.5f, 0.5f); // 画布缩放,理解一下,一张标有X,Y坐标的图片,缩放后,下面操作的坐标,都是按缩放后画布的坐标,也实际尺寸不同。如果是先scale再translate,则translate的坐标也是基于缩放后画布的坐标canvas.rotate(45); // 画布旋转(默认以原点,顺时针)// 6.绘图片Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);canvas.drawBitmap(bitmap, 50, 50, null);canvas.restore();// 7.绘文本canvas.drawText("CocoView", 50, 50, textPaint);canvas.save();Matrix matrix = new Matrix();matrix.postTranslate(300, 300);canvas.concat(matrix);canvas.skew(1, 0); // 倾斜canvas.drawRect(0, 0, 100, 100, rectPaint);canvas.restore();}}

效果图:

【Android】自定义View之Canvas的使用_第1张图片

Paint类:主要用来定义画笔的属性,不管是画图形、画文字、画图片,都是通过画笔来画,而画笔有粗有细、有各种颜色设置等,就在Paint类中定义。

Canvas类:画布,带有X,Y坐标系。可以在画布上画各种图形、线条、文字、图片,而所画出来的内容与效果,就是这个自定义View将要显示成的样子。

上述例子中只列举了常用几种图片的画法,当然还有很多图形画法没有列举出来,可参考Android API文档,也比较容易掌握。下面重点说一下画布的移动、缩放、 旋转、倾斜操作,与及save()、restore()的用法。

要灵活地掌握这些用法,建议,先了解一下View的绘制过程。可参考:

【Android】View绘制过程分析之measure

【Android】View绘制过程分析之layout

【Android】View绘制过程分析之draw

要明白一点就是:View的大小和相对于父布局的位置,是已经在measure()和layout()阶段中确定的了,而draw()操作是在这两个阶段之后的操作。我们可以理解为,在我们调用draw()方法绘制自定义View之前,父布局已经为这个View确定好了一个矩形的框框,我们在这个框框上放一张画布,我们在画布上作画。画布可以无限放大,可以随意移动位置,可以随意旋转,而真正显示给用户看到的样子,只是透过这个矩形框框所看到的部分。更形象的理解,我们在支架上固定放一相机,相机对面是一张大画板,你可以随意移动画板,随意涂鸦,而当按下快门,真正映成相片的那一个矩形框框的区域。

画布可以理解为一张带了X,Y坐标系的底图,以(0,0)为原点。

画布移动(translate):这个原点就偏离了View的原点(即那个矩形框框的左上角),可以这样理解,绘图是在画布上绘,不是在View上绘,所以这些方法用到的坐标,都是画布的坐标,按下快门,相机中所成的像才是View的效果。

画布旋转(rotate):可联想到你将现实中的画布、画板按时针方法旋转一个角度。旋转有一个基点,即以哪个点为支点去旋转。前面说到画布是有X,Y坐标系的,我们可以在脑海中联想,这个坐标系,全部已经画成了X,Y轴交叉的线条,整张画布就成了格子簿。假设旋转45度角,那我们看到的这些X,Y线,已经不是横、竖了,而是倾斜了45度角。但绘图是按布局的坐标去绘的。OK,我们得把自己的头倾斜45度,去看着画布绘图,这些我们眼里看到的画布又是正的了。注意:那个View矩形框框是不变的!

画布缩放(scale):与现实中画布不同,Canvas支持缩放。缩放是对整对画布缩放(这些可以理解画布为了张画有X,Y交叉线条的图片),坐标X,Y值与实现的值已经不同,还是要紧记一点,我们在画布上画,不管画布上X,Y值多大多小,我们都是按画布的坐标来画!

画布倾斜(skew):还记得以前学数学时,正方形、长方形,是怎样变成平行四边形的吗?两个参数,skew(画布的Y边向X轴方向倾斜的角度tan值,画布的X边向Y轴方向倾斜的角度tan值)。这些候,画布上X,Y线已经不再是垂直交叉了,构成的格格已经不再上正方形了。而不管画布的坐标系变成怎么样,都得按画布的坐标系来绘画。

经过以上画布的变换与图片的绘制后,“咔嚓"一声,拍照成像,View最终效果形成。

能理解上面的内容,就不难理解save()和restore()的作用了。

canvas.save();//在这中间,根据绘图需要,可对画布做各种移动、旋转、缩放、倾斜操作。canvas.restore();//在这之后,画布恢复成原来的样子,原点(0,0)与View框框原点对齐。

@容新华技术博客 - http://blog.csdn.net/rongxinhua - 原创文章,转载请注明出处


更多相关文章

  1. android手指缩放效果
  2. Android坐标系分析
  3. Andropid自定义组件-坐标详解
  4. Android 获取View的位置参数:x,y和相对父容器的偏移量以及中心点
  5. android实现图片平移、旋转、缩放
  6. Android 双击和手势的图片缩放
  7. Android通过手势实现的缩放处理
  8. Android图片按比例缩放

随机推荐

  1. android 这篇文章让我更加明白android数
  2. Android中ProgressBar的使用-通过Handler
  3. Android中使用WebView, WebChromeClient
  4. android开发学习笔记001a
  5. Android(安卓)4.0冰淇淋三明治SDK怎么下
  6. Android中资源文件夹res/raw和assets的使
  7. Android(安卓)TextView
  8. android:fastScrollEnabled和android:dra
  9. android内核字符驱动设备实战之---------
  10. Android取消EditText自动默认获取焦点行