第六章 一张白纸好作画—Canvas画布(1)

第六章 一张白纸好作画—Canvas画布

前面的相关章节,我们详细说明过Android UI组件的使用。通过前面章节的学习,开发者已经可以开发出令人满意的UI效果了。但是有的时候,我们需要实现更加漂亮的UI效果,此时可能就无法直接使用UI组件,而是需要自己画出各种UI效果了。

在Android中,Canvas就是一个画布,开发者可以在画布上绘制想要的任何东西。在本章中,我们将介绍Canvas及相关的技术。

6.1 Canvas画布介绍

6.1.1View Canvas—使用普通View的Canvas画图

从J2ME MIDLET时我们就知道Java提供了Canvas类,而目前在Android平台中,它主要任务为管理绘制过程, 就像一个画布,任何的绘画都将在这个画布上完成。

Canvas类有三个构造方法,分别为构造一个空的Canvas,从Bitmap中构造(2D)和从GL对象中创建(3D),具体如下:


Canvas();//一般使用在View中的Canvas

Canvas(Bitmap bitmap);//从2D对象中创建

Canvas(GL gl); //从3D对象中创建

由于Java先天的一些问题,基于设备硬件的处理速度考虑,3D的应用更多的需要使用C++的底层库来实现,这样才能有更好的用户体验。这里我们将重点介绍的是Canvas在2D中的功能。

先来看如何使用普通View的Canvas画图。

一般的,操作步骤如下:

1)定义一个自己的View :class your_view extends View{}。

2)重载View的onDraw方法:protectedvoid onDraw(Canvas canvas){}。

3)在onDraw方法中定义你自己的画图操作。

4)在代码或布局文件中使用。

例如:我们可以实现一个带边框文字的textview。代码片段如下所示。


// import略

public class ShadeTextView extends TextView {

public ShadeTextView(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

public void onDraw(Canvas canvas) {

super.onDraw(canvas);

drawText(canvas, 0xffff0000);

super.onDraw(canvas);

}

// 注:这里只做了单行的字处理

private void drawText( Canvas canvas, int bg) {

Paint paint = getPaint();

// 获取textview的文本

String text = String.valueOf(getText());

// 获取第一行文字的左边距

float startX = getLayout().getLineLeft(0);

// 获取第一行文字的底部距离

float startY =  getBaseline() ;

paint.setColor(bg);

canvas.drawText(text, startX + 1 , startY, paint);

canvas.drawText(text, startX, startY - 1 , paint);

canvas.drawText(text, startX, startY + 1 , paint);

canvas.drawText(text, startX - 1 , startY, paint);

}

}

在布局文件中使用:


<com.yourpackage.ShadeTextView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text=" 测试带阴影的文字"

android:textSize="20sp"/>

图6-1 带边框TextView的实现结果

在这里,我们新建了一个类ShadeTextView,继承自TextView类,重写了onDraw(Canvas canvas)方法,在这个方法里画出了边框。

6.1.2 Bitmap Canvas—使用普通Bitmap的Canvas画图

我们也可以定义自己的Bitmap,然后生成一个属于这个Bitmap的Canvas,并在其上进行你需要的绘画。最终可以自由的使用这个图片。

这种方式,主要用于自定义的绘制图形,和刷新比较快的、需要进行双缓冲防止闪屏的场合。

代码示例如下。


Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

// 必须将这个Bitmap放入View的Canvas中,画的图才会被显示出来

Canvas c = new Canvas(b);

6.1.3SurfaceView Canvas—使用SurfaceView的Canvas画图

前面看到如何使用普通View的Canvas画图和普通的图片的Canvas,Android为方便我们使用View的Canvas进行画图还封装一个类SurfaceView。SurfaceView方式和View方式的主要区别在于:SurfaceView中定义了一个专门的线程来完成画图工作,应用程序不需要等待View的刷图,提高了性能。View的方式适合处理量比较小,帧率比较小的动画,比如说象棋游戏之类的;而SurfaceView方式主要用在游戏,高品质动画方面的画图。

使用SurfaceView,一般步骤如下:

1)定义一个自己的SurfaceView:class your_SurfaceView extends extendsSurfaceView implements SurfaceHolder.Callback() {}

2)实现SurfaceHolder.Callback的3个方法:surfaceCreated()、surfaceChanged()、surfaceDestroyed()

3)定义自己的专注于画图的线程:class your_thread extends Thread

4)重载线程的run()函数(在SurfaceView 的surfaceCreated()中启动这个线程)

下面的示例代码详细说明了线程的处理过程。


// import略

public class YourViewThread extends Thread{

// 睡眠的毫秒数

private int sleepSpan = 100;

// 循环标记位

private boolean flag = false;

// 游戏界面的引用

private YourSurfaceView mYourSurfaceView;

private SurfaceHolder mSurfaceHolder = null;

public YourViewThread (YourSurfaceView mYourSurfaceView , SurfaceHolder mSurfaceHolder){

this. mYourSurfaceView = mYourSurfaceView;

this.mSurfaceHolder = mSurfaceHolder;

}

public void run(){

// 画布

Canvas c;

while(flag) {

c = null;

try {

// 锁定整个画布,在内存要求比较高的情况下,建议参数不要为null

c = mSurfaceHolder.lockCanvas(null);

synchronized (this.mSurfaceHolder) {

try{

mYourSurfaceView.onDraw(c);

} catch(Exception e) { }

}

} finally {

if (c != null) {

// 更新屏幕显示内容

mSurfaceHolder.unlockCanvasAndPost(c);

}

}

try {

// 睡眠sleepSpan毫秒

Thread.sleep(sleepSpan);

} catch(Exception e) { }

}

}

public void setFlag(boolean flag) {

// 设置循环标记

this.flag = flag;

}

}

--------------------------------------------

程序员赚钱不易 一定要学会理财

平安陆金所 隶属于平安集团的p2p平台

年投资回报率7%-9% 是替代银行理财的首选

个人经验 推荐投资安鑫或者有担保的彩虹项目

不要投资安e 那个几乎无法转让 想提前提现非常困难

网站链接 http://affiliate.lufax.com/action/36XBU

首次投资1000元即可额外赚几百元 不赚白不赚

--------------------------------------------

下面的示例代码详细说明了画图的过程。


// import略

public class YourSurfaceView extends SurfaceView

implements SurfaceHolder.Callback{

private YourViewThread mYourViewThread;

public YourSurfaceView(Activity activity) {

super(activity);

// 将SurfaceView画布的句柄传给刷新线程

mYourViewThread = new YourViewThread(this,getHolder());

getHolder().addCallback(this);

}

protected void onDraw(Canvas canvas) {

if(canvas == null) {

return;

}

}

@Override

public boolean onTouchEvent(MotionEvent event){

return true;

}

@Override

public boolean onKeyDown(int keyCode,KeyEvent event){

return false;

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {

// 当画布发生变化的时候会自动调用

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

// 当画布被创建的时候会自动调用

try{

// 启动刷新线程

mYourViewThread.setFlag(true);

mYourViewThread.start();

} catch(Exception ex){

mYourViewThread = new YourViewThread(this,getHolder());

mYourViewThread.setFlag(true);

mYourViewThread.start();

}

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

// 当画布被销毁的时候会自动调用

boolean retry = true;

mYourViewThread.setFlag(false);

while (retry) {

try {

mYourViewThread.join();

retry = false;

} catch (InterruptedException e) {

}

}

}

}

时间: 2024-11-09 09:14:30

第六章 一张白纸好作画—Canvas画布(1)的相关文章

第六章 一张白纸好作画—Canvas画布(5)

6.4.8区域 android.graphics.Region与Region.Op 在Canvas的绘画时,我们可能碰到止需要显示半个矩形,或者显示一部分图片,那么我们就要用到Canvas的设置区域的方法,有clipRect(Rect rect,Region.Op op).clipRegion(Region region)这两个方法.Region表示的是一个区域和Rect不同的是,它可以表示的一个不规则的样子,可以是椭圆.多边形等等,当然Region也可以表示一个矩形,而Rect仅仅是矩形. 同

第六章 一张白纸好作画—Canvas画布(2)

6.2 Canvas常用绘制方法 前面一节我们了解到如果创建一个画布,接下来我们就将要在这个画布上进行绘制.Android SDK的Canvas类中包含了一系列用于绘制的方法,方法分为3种类型,下面简单介绍这些常用的绘制方法. 1)Canvas类的几何图形(Geometry)方面的方法用于绘制点.绘制线.绘制矩形.绘制圆弧等. 其中一些主要的方法如表6-1所示: 方法 返回值 说明 drawARGB(int a, int r, int g, int b) void 将整体填充为某种颜色 draw

第六章 一张白纸好作画—Canvas画布(3)

6.4 Canvas绘制的辅助类 通过前面对Canvas的介绍,我们明白Canvas可以做很多事,绘画图形,变换等,当然在手机世界里我们看到的远远不是简单的图形就可以表现完全的,还有颜色,字体,等各种各样的元素组成,专门的工作交给专门的类来处理.下面我们介绍一些Canvas常用到的一些辅助类. 6.4.1画笔android.graphics.Paint 在Canvas绘制的辅助类中,使用频率最多的是画笔类-Paint.在Canvas的绘制的方法中都带有一个参数,Paint.这个参数就是画笔,Pa

第六章 一张白纸好作画—Canvas画布(4)

6.4.4路径android.graphics.Path 当我们的需求是一个不规则的图形的时候,Canvas的drawRect等方法就不行了,这里就要用到drawPath(Path path, Paint paint)方法来按路径绘画一个形状.Canvas还有一个方法clipPath(Path path).这个方法用于按照设计的路径来设置Canvas中的有效区域. 下面我们就介绍下路径类,它是一个多个点和图形的集合. Path的构造方法比较简单,如下: Path path1 = new Path

《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第六章  继承与建模高级应用 现在,你应该对实体框架中基本的建模有了一定的了解,本章将帮助你解决许多常见的.复杂的建模问题,并解决你可能在现实中遇到的建模问题. 本章以多对多关系开始,这个类型的关系,无论是在现存系统还是新项目的建模中都非常普遍.接下来,我们会了解自引用关系,并探索获取嵌套对象图的各种策略.最后,本章以继承的高级建模和实体条件结束. 6-1  获取多对多关联中的链接表 问题

JavaScript DOM编程艺术-学习笔记(第五章、第六章)

第五章: 1.题外话:首先大声疾呼,"js无罪",有罪的是滥用js的那些人.js的father 布兰登-艾克,当初为了应付工作,10天就赶出了这个js,事后还说人家js是c语言和self语言"约"的产物,(百度百科说的,这些).....一个可怜的孩子-js.然后命运弄"人",js此时已世人皆知.可能是因为js的毁誉参半,它老爸才不想承认它吧.如果js会说话,它可能会给它布兰登-艾克说,"你当初怎么不把*******在墙上".这

再读大道至简第六章

大道之简临近了尾声,作者也开始了“与前文相呼应”,第六章的内容大部分建立在前面五章的基础之上,对相关的名词进行了进一步的阐释,理解,对有关的概念进行了扩充. 一开始说了,语言只是工具,这几乎与第一章的内容相呼应,不讲JAVA/C/C++等等语言的好坏,只是把他们放在工具的层面来说.没有对语言的膜拜也没有对语言的漠视.语言再不同,只是工具不同,适用于不同的环境.就像是犁地不需要铲子,扫地需要扫把一样的.笔者借由各种语言只是工具来引出了,那张幻灯片.看清代码.方法.工程.组织的关系. 在代码.方法.

阅读笔记3——《大道至简》第四、五、六章

“流于形式的沟通,可能是使得你的项目被不断推翻和不断延迟的最直接原因”,这是第四章的最后一句话,是我印象最深刻的一句话. 当我们在与客户交流时,要用客户能懂得方式,并且要保障每一次沟通的有效性,求道于盲是没有错误的,错误的是你睁着眼睛.现在很多公司和客户谈项目时总喜欢去吃饭,吃饭是没有错误的,但最终的结果大多是以酒醉收场.所以就需要最有效的沟通方式来减少各方面的损失,而这个最有效的方式则是通过各方面考究查询得知的.除此之外,我们在做项目时,要记得留下整个项目的历史记录,例如,在需求阶段,与谁联系

MiS603开发板 第十六章 图像之VGA接口测试

作者:MiS603开发团队 日期:20150911 公司:南京米联电子科技有限公司 论坛:www.osrc.cn 网址:www.milinker.com 网店:http://osrc.taobao.com EAT博客:http://blog.chinaaet.com/whilebreak 博客园:http://www.cnblogs.com/milinker/ MiS603开发板 第十六章 图像之VGA接口测试 第十六章图像之VGA接口测试 在本章开始介绍视频图像处理开发平台的硬件结构,主要包括