作为Android Graphics专题的开篇。毫无疑问,我们将讨论Android UI技术的核心概念——Canvas。

Canvas是Android UI框架的基础,在Android的控件体系中。全部容器类、控件类在实现上都依赖于Canvas。界面的绘制实质上都是Canvas绘制的。本文将讨论Canvs的由来。并通过实例展示Canvas的基础使用方法。

对于应用开发而言,我们能够不去深究Canvas与Android
控件体系的实现细节,但明确Canvas与控件的关联有助于我们更好的使用Canvas。Android控件体系不是了解的朋友能够參见博文《Android原理揭秘系列之View、ViewGroup》。

先看下Android全部控件的基类——View.java的代码片段:


protected void onDraw(Canvas canvas) {
}
….

熟悉Andriod应用开发的人对onDraw方法一定不会陌生。View基类里onDraw方法里是空的。但请注意,方法传入了形參——Canvas对象,也就是说。Canvas对象是UI体系流程中已经创建好的。我们直接拿来用就可以,一般不须要自己构造。Canvas的典型使用场景是,在自己定义控件重载基类的onDraw方法,并在onDraw方法中通过Canvas绘制我们想要的图形、图片等效果。

我们再看看容器类的基类——ViewGroup.java的dispatchDraw方法的代码片段:

protected void dispatchDraw(Canvas canvas) {

for (int i = 0; i < count; i++) {

more |= drawChild(canvas, child, drawingTime);
}

}

dispatchDraw方法是ViewGroup分发绘制子View的核心函数,其通过drawChild方法详细绘制各个子View。这里我们仅仅须要注意Canvas对象的出现位置,相同。Canvas作为形參从dispatchDraw方法传入。并传给drawChild方法用以绘制子view。

通过View和ViewGroup两个核心函数的代码片段分析。我们可以很清晰的明白Canvas在控件体系中的作用。以及我们接下来将讨论的Canvas使用方法的canvas对象来自何处。

Canvas在概念上能够理解为其他编程语言中的画布,在画布中。我们能够绘制各种图形。也能够绘制图片,更深层次的。如上ViewGroup的dispatchDraw方法所描写叙述的。我们能够通过变换Canvas,进而在容器内中自己定义的绘制子控件。

本文仅仅讨论Canvas的基础使用方法,即在自己定义控件重载的onDraw方法中,使用Canvas来绘制主要的图形、图像等基础使用方法。

Android的官方SDK中罗列了Canvas的全部API,可点击具体查看

这里罗列下在实际应用开发中用得很普遍的几个API:

1) 
绘制Bitmap:drawBitmap、drawPicture

2) 
绘制颜色:drawColor、drawARGB

3) 
绘制基本形状:drawPoint、drawLinedrawCircledrawArc、drawRect、drawRoundRect

4) 
绘制剪切区:drawPath、clipPathclipRectclipRegion

5) 
变换Canvas:save、restore、translate、scale、rotate、concat(Matrix
matrix)、setMatrix(Matrix
matrix)

6) 
绘制顶点数据:drawVertices、drawBitmapMesh

上面的六项基本概况了Canvas的使用得最普遍的API。各API的详细含义和使用方法參见SDK。熟练掌握这些API的功能和使用方法基本能够满足开发须要。

以下通过两个代码演示样例来演示Canvas的基本使用方法。

演示样例1:绘制Bitmap

private static class SampleView extends View {
private Bitmap mBitmap;
private Bitmap mBitmap2;
private Bitmap mBitmap3;
private Bitmap mBitmap4;
public SampleView(Context context) {
super(context);
setFocusable(true); java.io.InputStream is;
is = context.getResources().openRawResource(R.drawable.beach);
BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bm;
opts.inJustDecodeBounds = true;
bm = BitmapFactory.decodeStream(is, null, opts);
opts.inJustDecodeBounds = false;
opts.inSampleSize = 4;
bm = BitmapFactory.decodeStream(is, null, opts);
mBitmap = bm; //通过配置參数解码生成Bitmap is = context.getResources().openRawResource(R.drawable.frog);
mBitmap2 = BitmapFactory.decodeStream(is); //通过打开资源ID直接解码图片 int w = mBitmap2.getWidth();
int h = mBitmap2.getHeight();
int[] pixels = new int[w*h];
mBitmap2.getPixels(pixels, 0, w, 0, 0, w, h);
mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h,
Bitmap.Config.ARGB_8888);
//通过缓冲区数据构造Bitmap
mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h, Bitmap.Config.ARGB_4444); } @Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
Paint p = new Paint();
p.setAntiAlias(true); //设置防锯齿
canvas.drawBitmap(mBitmap, 10, 10, null);
canvas.drawBitmap(mBitmap2, 10, 170, null);
canvas.drawBitmap(mBitmap3, 110, 170, null);
canvas.drawBitmap(mBitmap4, 210, 170, null); //通过drawBitmap绘制图 }
}

演示样例1通过继承基类View实现了一个绘制Bitmap的自己定义View SampleView,SampleView在构造函数中通过几种不同的方式分别构造了四个不同的Bitmap,在onDraw方法中,通过onDraw方法传入的canvas绘制Bitmap。

这样实现的控件在界面上将依据不同的坐标位置绘制出四幅图片的效果。注意,因为Android
View的onDraw方法在界面显示、隐藏、遮挡等非常多场合都会被系统频繁调用,因此,像构造Bitmap这种耗费较大内存资源的工资不应该放在onDraw方法中去运行。

演示样例2:绘制顶点数据实现变形效果

  private static class SampleView extends View {
private final Paint mPaint = new Paint();
private final float[] mVerts = new float[10];
private final float[] mTexs = new float[10];
private final short[] mIndices = { 0, 1, 2, 3, 4, 1 }; private final Matrix mMatrix = new Matrix();
private final Matrix mInverse = new Matrix(); private static void setXY(float[] array, int index, float x, float y) {
array[index*2 + 0] = x;
array[index*2 + 1] = y;
} public SampleView(Context context) {
super(context);
setFocusable(true); Bitmap bm = BitmapFactory.decodeResource(getResources(),
R.drawable.beach);
Shader s = new BitmapShader(bm, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
mPaint.setShader(s);//通过BitmapShader设置Paint的Shader float w = bm.getWidth();
float h = bm.getHeight();
// construct our mesh
setXY(mTexs, 0, w/2, h/2);
setXY(mTexs, 1, 0, 0);
setXY(mTexs, 2, w, 0);
setXY(mTexs, 3, w, h);
setXY(mTexs, 4, 0, h); //初始化图片纹理映射坐标 setXY(mVerts, 0, w/2, h/2);
setXY(mVerts, 1, 0, 0);
setXY(mVerts, 2, w, 0);
setXY(mVerts, 3, w, h);
setXY(mVerts, 4, 0, h);//初始化顶点数据数组 mMatrix.setScale(0.8f, 0.8f);
mMatrix.preTranslate(20, 20);
mMatrix.invert(mInverse); //初始化变形矩阵
} @Override protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC); //绘制背景色
canvas.save(); //变形canvas前先保存canvas现场
canvas.concat(mMatrix); //设置变换矩阵 canvas.drawVertices(Canvas.VertexMode.TRIANGLE_FAN, 10, mVerts, 0,
mTexs, 0, null, 0, null, 0, 0, mPaint);
//绘制当前顶点坐标和纹理坐标决定的图片Paint,得到图片变形效果。 canvas.translate(0, 240);//向下平移canvas
canvas.drawVertices(Canvas.VertexMode.TRIANGLE_FAN, 10, mVerts, 0,
mTexs, 0, null, 0, mIndices, 0, 6, mPaint);
//绘制当前顶点坐标和纹理坐标和索引数组决定的图片Paint,得到另外的图片变形效果。 canvas.restore();//变换完毕后恢复canvas现场
} @Override
public boolean onTouchEvent(MotionEvent event) {
float[] pt = { event.getX(), event.getY() };
mInverse.mapPoints(pt); // 依据当前的触摸位置变换Marix
setXY(mVerts, 0, pt[0], pt[1]); //据触摸的位置变换顶点坐标
invalidate();//刷新界面。触发onDraw方法被再次调用
return true;
} }

演示样例2是Canvas的一个比較综合性的使用方法演示样例,用到了canvas的多个API,理解了该演示样例。对Canvas的使用方法基本就达到了比較熟练的程度。该演示样例的一些新的概念如Paint、Shader、Matrix等概念兴许专题会作有专门的介绍,敬请关注。

演示样例2有例如以下一些知识点:

1) 用户的触摸事件在onTouchEvent中传入,通过传入event參数能够获取当前触摸膜的坐标点,并依据这个坐标位置參数来改变算法的相关參数,进而达到依据不同的坐标位置来达到变形的目的。

2) 
调用View的invaidate方法能够触发View的重绘流程。重而触发onDraw方法的调用。

3)能够通过canvas的drawColor方法来绘制View的背景色。

4) 因为在onDraw方法中传入的Canvas參数是一个引用。该canvas对象在其它地方还会使用,因此。假设绘制中会改变canvas的几何參数,须要在变换前后採用canvas.save()、canvas.restore()方法对来备份和恢复canvas现场。

注意,这两个方法必须成对出现。否则会导致严重的波及问题。

5) 
变换canvas的几何參数能够通过concat连接Maxrix矩阵或者translate平移、scalse缩放、rotate旋转等方法来实现。

6)能够通过drawVertices方法绘制具有变形图片的效果,详细变形的样式取决于顶点坐标、纹理坐标、索引数组和Paint设置的BitmapShader。

灵活使用该API能够以2D的API实现近似3D的效果。与drawVertices类似的API还有drawBitmapMesh,能够实现基于网格顶点的复杂3D效果。

演示样例2的执行效果參见下图:

本文是Android Canvas的基础篇,主要讨论Canvas的一些基本概念和经常使用API,兴许文章中将继续涉及Canvas的方方面面。

Android
Graphics专题的下一篇文章将聚焦Graphics中用得很普通的概念——Paint。敬请期待。


































































































我的手机专卖店,欢迎各位看官捧场http://vpclub.octech.com.cn/ztewd/9495.html

本文为原创文章,转载请注明出处http://blog.csdn.net/droidpioneer

Android Graphics专题(1)--- Canvas基础的更多相关文章

  1. android.graphics(1) - Paint, Canvas, drawLine, drawPoint, drawRect, drawRoundRect, drawCircle, drawOval, drawArc

    一.Paint与Canvas 像我们平时画图一样,需要两个工具,纸和笔.Paint就是相当于笔,而Canvas就是纸,这里叫画布. 所以,凡有跟要要画的东西的设置相关的,比如大小,粗细,画笔颜色,透明 ...

  2. 【转】android Graphics(四):canvas变换与操作

    android Graphics(四):canvas变换与操作 分类: 5.andriod开发2014-09-05 15:05 5877人阅读 评论(18) 收藏 举报   目录(?)[+]   前言 ...

  3. android Graphics(四):canvas变换与操作

    前言:前几篇讲解了有关canvas绘图的一些操作,今天更深入一些,讲讲对画布的操作,这篇文章不像前几篇那么容易理解,如果以前没有接触过画布的童鞋可能比较难以理解,为什么会这样.我尽量多画图,让大家更清 ...

  4. Canvas: trying to use a recycled bitmap android.graphics.Bitmap@XXX

    近期在做和图片相关显示的出现了一个问题,整理一下思路.分享出来给大家參考一下: Exception Type:java.lang.RuntimeException java.lang.RuntimeE ...

  5. android SurfaceView绘制 重新学习--基础绘制

    自从大二写了个android游戏去参加比赛,之后就一直写应用,一直没用过SurfaceView了,现在进入了游戏公司,准备从基础开始重新快速的学一下这个,然后再去研究openGL和游戏引擎. 直接上代 ...

  6. android Graphics(三):区域(Range)

    前言:最近几天对画图的研究有些缓慢,项目开始写代码了,只能在晚上空闲的时候捯饬一下自己的东西,今天给大家讲讲区域的相关知识,已经想好后面两篇的内容了,这几天有时间赶紧写出来给大家.有关界面开发的东东内 ...

  7. android Graphics(一):概述及基本几何图形绘制

    前言:我最近想抽空研究研究android的各种特效,android的特效真是其它平台无法比拟的,而且一个漂亮的UI交互,会给APP增色不少,而学习特效之前,有关graphics绘图的基础知识是必不可少 ...

  8. 【Android开发日记】之基础篇(二)——Android的动画效果

          什么是动画,动画的本质是通过连续不断地显示若干图像来产生“动”起来的效果.比如说一个移动的动画,就是在一定的时间段内,以恰当的速率(起码要12帧/秒以上,才会让人产生动起来的错觉)每隔若干 ...

  9. android.graphics.Matrix

    Matrix类包含了一个3x3的矩阵用来改变坐标,它没有一个构造器来初始化它里边的内容,所以创建实例后需要调用reset()方法生成一个标准matrix,或者调用set..一类的函数,比如setTra ...

随机推荐

  1. C++基础学习笔记----第七课(面向对象的基本概念)

    主要讲面向对象的基本概念和一些概念,以及实现简单的面向对象C++程序. 类和对象 基本概念 类和对象是面向对象中的两个基本概念,类是指一类事物,是一个抽象的概念.对象是指某一个类的实体,是一个具体存在 ...

  2. Jsp中使用数据库连接池.

    原文 Jsp中使用数据库连接池. 1. 在tomcat服务器目录下面的conf中找到一个叫Context.xml的配置文件,在其中加入以下代码 <Resource name="jdbc ...

  3. Jetty支持Windows认证

    WAFFLE是什么? Jetty增加WAFFLE支持 DEMO 小结 WAFFLE是什么? WAFFLE是一个Windows认证框架,支持Negotiate, NTLM和Kerberos认证.WAFF ...

  4. jquery动态改变背景颜色插件

    GETHUB下载地址 背景颜色用animate方法时时无法改变颜色的 所以要使用插件进行补充. 用法: <!DOCTYPE html> <html> <head> ...

  5. MFC程序的消息处理顺序

    MFC应用程序中处理消息的顺序 1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc()  该 ...

  6. 基础知识(3)- Java的基本程序设计结构

    3.1 一个简单的Java应用程序 3.2 注释 3.3 数据类型  3.3.1 整型  3.3.2 浮点类型  3.3.3 char类型  3.3.4 boolean类型 3.4 变量  3.4.1 ...

  7. 3xian退役贴【深思。】

    这是原文: 最后一天,漫天飘起了雪花,假装欢送我离去. 这次WF之战不太顺利,早期的C题大概花了1秒钟构思,然而由于输出格式多了一个空格直到两个半小时才逃脱Wrong Answer的纠缠.还好lynn ...

  8. android binder机制之——(创建binder服务)

      Binder机制编程 前面的几篇文章具体介绍了android中binder机制的方方面面,相信你对binder机制已经有了较深刻的理解.俗话说得好"学以致用",以下我们就通过在 ...

  9. C语言信号学习笔记

    在C语言中,对于错误有很多处理方式.然而,今天学习了信号处理,感觉这种处理方式十分灵活,特此记录. 关于信号处理的函数包含于头文件<signal.h>中.所谓的信号,多指出乎程序员意料的行 ...

  10. linux ifconfig命令使用详解

    Linux下网卡命名规律:eth0,eth1.第一块以太网卡,第二块.lo为环回接口,它的IP地址固定为127.0.0.1,掩码8位.它代表你的机器本身. 1.ifconfig是查看网卡的信息. if ...