Android 图形 I-Canvas&Drawable

本文介绍了Android中的2D图形绘制,包括Canvas的使用,如何在View和SurfaceView上绘图,以及Drawable对象的创建和应用。重点讲解了在自定义View的onDraw()方法中使用Canvas绘制图形,SurfaceView的绘图机制,以及如何通过XML和资源文件创建Drawable对象。同时,文章探讨了Shape Drawable和Nine-patch技术,后者用于创建可拉伸的图片背景。
摘要由CSDN通过智能技术生成

概述:

Android framework提供了一组2D绘制API, 让我们可以在一个canvas上渲染我们自定义的图形, 或者修改View成自定义的外观. 绘制2D图形的经典方式如下:

a.      在自己layout的View上绘制图形或者动画. 这种方式下, 绘制工作由Android的普通View层绘制完成, 我们只需要简单的将图形放入View即可.

b.      在Canvas上绘制自己的图形. 这种方式下, 我们必须调用合适的类的onDraw()方法(传入我们自定义的Canvas), 或者Canvas的某个draw…()方法(比如drawPicture()). 这样一来我们也可以控制所有的动画了.

选项a, 绘制在一个View上. 如果我们绘制简单的不需要动态改变的图形, 或者不是性能密集型游戏的时候, 这种做法是我们的最佳选择. 比如如果我们想要显示一张静态的图片或者一个预定义的动画的时候, 那么我们应该使用这种方式.

选项b, 在一个Canvas上绘制. 如果我们的APP需要经常重绘它自己的时候, 用这种方式更加合适. 通常一款游戏APP应该使用Canvas. 实现这种方式有不止一种方法:

1.      在UI线程中执行. 我们在自己的layout中创建自定义的View组件, 并调用它的invalidate()方法然后实现onDraw()回调方法.

2.      在独立的线程中执行. 我们操作一个SurfaceView, 然后以最快的速度向Canvas中绘制图形. 这种情况下不需要invalidate().

使用Canvas绘图:

当我们写一个需要专业绘图功能或者要对图像进行动画控制的APP的时候, 我们就需要Canvas. 绘制事件的操作在onDraw()方法中, Canvas就像一块画布, 我们需要做的就是将图绘制在Canvas上面. 当处理一个SurfaceView对象的时候, 我们可以通过SurfaceHolder.lockCanvas()方法获取一个Canvas. 如果我们需要创建一个新的Canvas,那么必须在绘制执行之前为其定义一个Bitmap. Bitmap是Canvas必须的. 我们可以这样设置一个新的Canvas:

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

这样我们的Canvas就会将这个bitmap绘制在它上面了. 在绘制完了之后我们可以将Bitmap从一个Canvas通过Canvas.drawBitmap(Bitmap, …)方法转移到另一个Canvas. 官方推荐我们通过View.onDraw()或者SurfaceHolder.lockCanvas()方法绘制最终的图片到一个Canvas.

Canvas类拥有它自己的绘制方法, 比如drawBitmap(…), drawRect(…), drawText(…)等. 其它我们可能用到的类也同样拥有draw()方法. 比如我们可能拥有一些Drawable对象, 我们希望可以将它们放入Canvas显示. Drawable拥有其自己的draw()方法并将Canvas作为它的参数.

在View上绘图:

如果我们的APP不需要大量的处理图像或者高帧率的图像, 那么应该考虑创建一个自定义的View组件并且在View.onDraw()方法中使用Canvas绘制图形. 这样做最方便之处在于Android framework将会为我们提供一个预定义的Canvas让我们在上面绘制想要的东西.

想要实现上面的步骤, 首先需要继承View类(或者其子类), 然后定义onDraw()方法. 该方法将会在View绘制它自己的时候被Android framework调用. 我们可以在这里处理所有的绘制操作. onDraw()方法会传入一个Canvas, 只需要对其进行绘制既可. Android framework将会在需要的时候调用onDraw()方法. 在APP想要重绘的时候, 必须调用invalidate()方法. 这表示我们想要View被绘制, 然后Android将会调用其onDraw()方法.

在View组件的onDraw()内部, 我们可以使用传入的Canvas的draw…()方法, 或者其它类的draw(Canvas)方法来实现所有的绘制操作. 一旦onDraw()方法结束了, Android framework将会使用我们的Canvas来绘制一个系统持有的Bitmap.

如果想要重绘一个非主线程的View, 我们必须调用postInvalidate()方法.

在SurfaceView上绘图:

SurfaceView是一个特别的View子类, 它提供了view层专用的绘图层. 这样可以为绘制surface提供一个应用的辅助线程, 而不需要等待系统View层准备好了才能绘制. 辅助线程可以绘制它自己的Canvas.

想要实现这个, 首先需要创建一个继承SurfaceView的类. 该类还应该实现SurfaceHolder.Callback接口. 这个子类将会通知我们底层Surface的事件, 比如它什么事件创建, 改变或者销毁. 这些事件很重要, 这样我们就可以知道什么时候应该开始绘制, 是否需要根据新的surface属性进行调整, 以及什么时候停止绘制和停止任务. 在我们的SurfaceView类中, 也可以定义自己的辅助线程类, 它将会处理所有的给Canvas的绘制工作.

我们不应该直接处理Surface对象, 而应该通过SurfaceHolder类处理它. 当我们的SurfaceView初始化的时候, 通过getHolder()取得SurfaceHolder. 然后应该通过addCallback()方法提示SurfaceHolder我们将要接收它的回调(从SurfaceHolder.Callback). 然后重写SurfaceHolder.Callback中的方法.

为了从辅助线程中绘制Surface Canvas, 我们必须将SurfaceHandler传递给线程, 然后通过lockCanvas()检索Canvas. 我们现在就可以在Canvas上绘制想要的东西了. 一旦绘制结束之后, 调用unlockCanvasAndPost()方法, 将Canvas对象传入. 现在Surface将会绘制我们的Canvas了. 每次我们想要重新绘制的时候, 都需要再次处理locking和unlocking操作.

Drawable:

Android提供了一个自定义2D图像库来给我们绘制形状和图像. 我们将会在android.graphics.drawable包中找到我们可以用来绘制二维图像的常用类.这个小节将会讨论使用Drawable对象绘制图像和如何使用几个drawable的子类的基本用法.

Drawable表示”一些可以被绘制出来的东西”.它被扩展为多个应用于不同对象的子类, 包括BItmapDrawable, ShapeDrawable, PictureDrawable, LayerDrawable等. 当然我们还可以根据需求来自定义drawable类. 有三种方式可以定义和初始化一个Drawable: 使用一个保存在工程中的图片资源文件; 使用一个定义了drawable属性的XML文件; 使用普通的类构造方法. 下面将介绍前两种方法.

从图片资源文件创建Drawable:

一个很简单的使用图片的方法就是使用代码关联到工程中的图片资源文件. 可以支持的文件类型有: PNG, JPG和GIF. 这种方法十分适用于APP的图标, logo或者其他图片, 比如在游戏中的图片. 想要使用一个图片资源只需要将图片文件添加到工程的res/drawable/目录下. 从那里我们可以从其他XML文件或者代码中关联这个图片资源. 不管在哪, 我们都需要使用资源ID来关联图片资源, ID不带扩展名, 比如my_image.png关联的时候就是my_image. 这里需要注意的是, 保存在res/dr

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值