多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
### Android中的drawable和bitmap ### - 前言 - Android 系统提供了ImageView显示普通的静态图片,也提供了AnimationDrawable 来开发逐帧动画,还可通过Animation 对普通图片使用补间动画。 - 图片不仅可以使用ImageView 来显示,也可作为Button 、Window 的背景。从广义的角度来看, Android 应用中的图片不仅包括*.png 、*.jpg、*.gif 等各种格式的位图, 也包括使用XML 资源文件定义的各种Drawable 对象。 - 为Android 应用增加了Drawable资源之后,Android SDK 会为这份资源在R 清单文件中创建一个索引项: `R.drawable. file name `。 - 接下来既可在XML 资源文件中通过@drawable/file_name 访问该Drawable 对象, 也可在Java 代码中通过`R.drawable.file name `访问该Drawable 对象。需要指出的是,R.drawable.file name 是一个int 类型的常量,它只代表Drawable对象的ID,如果Java 程序中需要获取实际的Drawable对象,则可调用Resources 的getDrawable(int id)方法来实现。当然如果ImageView使用drawable来显示,可以通过getDrawable()来获取显示的drawable - drawable( android.graphics.drawable.Drawable ) - drawable是一个抽象的概念,凡是可以被画出来的东西都称之为drawable。[官网介绍](https://developer.android.com/reference/android/graphics/drawable/Drawable.html)drawable不可见,Drawables采取了多种形式呈现在我们面前,比如 - Bitmap: 位图----最简单的Drawable, PNG or JPEG图片。 - Nine Patch: 9patch图----可以局部缩放,定义文本区域的.9patch图片 - Vector:矢量---在XML文件中定义的一个drawable作为一组点,线和曲线及其关联的颜色信息。可以缩放这种类型的可绘制,而不会损失显示质量。 - Shape: 形状:包含简单的绘图命令而不是原始位图,允许它在某些情况下更好地调整大小。 - Layers: 层:一个复合的drawable,它可以在彼此之上绘制多个底层的drawable。 - States: 状态:根据其状态选择一组可绘图之一的复合绘图。 - Levels: 级别:根据其级别选择一组可绘图之一的复合绘图。 - Scale: 比例:一个单个可抽出的单个可抽取的组合,其总体大小根据当前级别进行修改。 - Drawable 是一个抽象的概念, 而 Bitmap 是其存在的实体之一。可以简单地理解为 Bitmap 储存的是 像素信息,Drawable 储存的是 对 Canvas 的一系列操作。而 BitmapDrawable 储存的是「把 Bitmap 渲染到 Canvas 上」这个操作。 - Drawable一般都是通过xml文件来定义,当然也可以通过代码来创建具体的Drawable对象,getResource().getDrawable()即可。只是用代码创建稍显复杂。 - Drawable的的内部宽/高(固有宽高)这个参数很重要,通过getIntrinsicHeight()和getIntrinsicWidth()获得(如果没有固有宽高,默认是-1,比如颜色构成的drawable,当然不同的子类返回的值也是不一样),但是不是所有的Drawable都有内部宽/高,比如一个颜色所形成的Drawable就没有这个概念,而且Drawable的宽高概念并不等同于它的大小,一般来说Drawable没有大小的概念,当被用作View的背景是,Drawable会被拉伸至view的同等大小 - - 自定义drawable(使用场景还是比较少,但是某些情况,还最合适) - 一般没有必要自定义Drawable,因为自定义drawable无法在xml文件中使用,这就降低了自定义drawable的使用范畴,但是某些情况可以使用。自定义方式和view差不多,但是没有那么复杂,它是轻量级的,比如想写一个圆形的drawable,但是通过xml来写一个圆形的drawable是很困难的, 并不是说不好写,而是,如果一个view的尺寸忽大忽小,是变化的,那么有些时候这个圆形就会被拉伸或者压扁变成椭圆,但是如果自定义来绘制一个圆形的drawable作为view的背景时,它的半径是可以随着view变化而变化的 - 一般只需要重写void draw (Canvas canvas)方法,而且从Android7.0开始,自定义drawable可以用于XML形式,官网介绍[这里](https://developer.android.com/reference/android/graphics/drawable/Drawable.html#draw(android.graphics.Canvas)%EF%BC%8C), 可以以多种方式在XML中使用自定义可绘制类drawable: - 使用完全限定类名作为XML元素名称。对于此方法,自定义drawable类必须是公共顶级类。 - ![](http://i.imgur.com/ETCKoUB.png) - 使用drawable作为XML元素名称,并从类属性中指定完全限定的类名。此方法可用于公共顶层类和公共静态内部类。 - ![](http://i.imgur.com/aJsvcr0.png) - 一个颜色资源,也可以用作XML的可绘制。`android:drawable="@color/green"` - drawable的层次结构(关于drawable的几个子类常用可以参考Android开发艺术探讨第六章,也可以参考[视频讲解](http://edu.csdn.net/course/detail/1923/29836?auto_start=1)) - [大图请点击这里](http://i.imgur.com/jo62b5Q.png) - ![](http://i.imgur.com/jo62b5Q.png) - Android种支持的图片格式 - PNG----推荐 - JPG----可接受的 - GIF----支持但是不推荐 - 当需要一个图片资源作为drawable,可以如下图 - ![](http://i.imgur.com/P9PDEqT.png) - Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。我们理解为一种存储对象比较好。 - aapt在构建过程中,位图文件可以通过工具进行无损图像压缩来自动优化。例如,不需要256色以上的真彩色PNG可以使用调色板转换为8位PNG。这将导致质量相同的图像,但需要更少的内存。因此,请注意,放置在此目录中的图像二进制文件可能在构建期间发生更改。如果您打算将图像作为位流读取,以便将其转换为位图,请将图像放在res/raw/文件夹中,而不是将其优化,也就是放在mipmap或者drawable文件夹下的位图会被优化。 - 层次结构([大图点击这里](http://i.imgur.com/2ap9PGQ.png)) - ![](http://i.imgur.com/2ap9PGQ.png) - 大部分时候,我们只要把图片放在`/res/drawable/`目录下,就可以在程序中通过该图片对应的资源、ID 来获取封装该图片的Drawable对象。但由于手机系统的内存比较小,如果系统不停地去解析、创建Bitmap 对象, 可能由于前面创建Bitmap 所占用的内存还没有回收, 而导致程序运行时引发OutOfMemory 错误。所以Android 为Bitmap 提供了上面两个方法`boolean isRecycled()`和`void recycle()`来判断它是否已回收,以及强制Bitmap回收自己。 - Bitmap是Drawable,Drawable不一定是Bitmap .就像拇指是指头,但不是所有的指头都是拇指一样 - ![](http://i.imgur.com/Q6xKOJi.png) - Drawable在内存占用和绘制速度这两个非常关键的点上胜过Bitmap - 总结 - Bitmap是用来显示的实际数据,它在概念上隶属于Drawable,但是与Drawable之间不是继承关系。 - Bitmap继承Parcelable,是一个可以跨进程传输的对象,BitmapDrawable继承Drawable,可Drawable只是一个抽象类,此类是一个存放数据流的载体。 - Bitmap 并没有实现 Drawable,二者如何联系呢? - BitmapDrawable - public class BitmapDrawable extends Drawable {......} - Drawable 类中有一个私有的静态方法drawableFromBitmap(): ~~~ private static Drawable drawableFromBitmap(Resources res, Bitmap bm, byte[] np, Rect pad, Rect layoutBounds, String srcName) { if (np != null) { return new NinePatchDrawable(res, bm, np, pad, layoutBounds, srcName); } return new BitmapDrawable(res, bm); } ~~~ * * * * * - 通过 BitmapDrawable 的构造函数,使得 Bitmap 可以转换为 Drawable。同理: BitmapDrawable 的 getBitmap 方法也会返回 bitmap对象: ~~~ public final Bitmap getBitmap() { return mBitmapState.mBitmap; } ~~~ - Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。我们理解为一种存储对象比较好。 - Drawable - 作为Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然还提供一些高级的可视化对象,比如渐变、图形等。 - Canvas - 名为画布,我们可以看作是一种处理过程,使用各种方法来管理Bitmap、GL或者Path路径,同时它可以配合Matrix矩阵类给图像做旋转、缩放等操作,同时Canvas类还提供了裁剪、选取等操作。 - Paint - 我们可以把它看做一个画图工具,比如画笔、画刷。他管理了每个画图工具的字体、颜色、样式。 - 参考链接 - [Android中Bitmap和Drawable ](http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0605/1333.html) - [Bitmap和Drawable的区别,为什么要用bitmap?](https://www.zhihu.com/question/29561539) - [Android中Drawable Bitmap Canvas Paint之间区别 ](http://www.cnblogs.com/playing/archive/2011/05/10/2042241.html) - [Android 中 Bitmap 和 Drawable 相互转换的方法](http://blog.csdn.net/l_lhc/article/details/50923372) - [Android中Bitmap和Drawable ](http://dyh7077063.iteye.com/blog/970672) - [简单谈谈Resource,Drawable和Bitmap之间的转换 ](http://www.cnblogs.com/rayray/p/3429708.html) - [Android Drawable Resource学习(二)、BitmapDrawable和Bitmap ](http://blog.csdn.net/lonelyroamer/article/details/8147542) - [Bitmap类用法 详细说明](http://blog.csdn.net/ymangu666/article/details/37729109) - [Android图像处理之Bitmap类](http://www.open-open.com/lib/view/open1333418945202.html) - [Android Bitmap深入介绍(一)---基础](http://blog.csdn.net/xxxzhi/article/details/51607765) - [android Bitmap.Config的用法介绍](http://wangxuefang.iteye.com/blog/1955910) - [Android Bitmap 全面解析](http://blog.csdn.net/kinglearnjava/article/details/44676351) - BitmapFactory - 创造bitmap,通过解码文件、流、字节数组等,BitmapFactory 是一个工具类,它提供大量的方法,这些方法可用于从不同的数据源来解析、创建Bitmap 对象。 - 结构层次图([大图点击这里](http://i.imgur.com/Ucf3OXT.png)) - ![](http://i.imgur.com/Ucf3OXT.png)