### 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類必須是公共頂級類。
- 
- 使用drawable作為XML元素名稱,并從類屬性中指定完全限定的類名。此方法可用于公共頂層類和公共靜態內部類。
- 
- 一個顏色資源,也可以用作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)
- 
- Android種支持的圖片格式
- PNG----推薦
- JPG----可接受的
- GIF----支持但是不推薦
- 當需要一個圖片資源作為drawable,可以如下圖
- 
- Bitmap
- 稱作位圖,一般位圖的文件格式后綴為bmp,當然編碼器也有很多如RGB565、RGB888。作為一種逐像素的顯示對象執行效率高,但是缺點也很明顯存儲效率低。我們理解為一種存儲對象比較好。
- aapt在構建過程中,位圖文件可以通過工具進行無損圖像壓縮來自動優化。例如,不需要256色以上的真彩色PNG可以使用調色板轉換為8位PNG。這將導致質量相同的圖像,但需要更少的內存。因此,請注意,放置在此目錄中的圖像二進制文件可能在構建期間發生更改。如果您打算將圖像作為位流讀取,以便將其轉換為位圖,請將圖像放在res/raw/文件夾中,而不是將其優化,也就是放在mipmap或者drawable文件夾下的位圖會被優化。
- 層次結構([大圖點擊這里](http://i.imgur.com/2ap9PGQ.png))
- 
- 大部分時候,我們只要把圖片放在`/res/drawable/`目錄下,就可以在程序中通過該圖片對應的資源、ID 來獲取封裝該圖片的Drawable對象。但由于手機系統的內存比較小,如果系統不停地去解析、創建Bitmap 對象, 可能由于前面創建Bitmap 所占用的內存還沒有回收, 而導致程序運行時引發OutOfMemory 錯誤。所以Android 為Bitmap 提供了上面兩個方法`boolean isRecycled()`和`void recycle()`來判斷它是否已回收,以及強制Bitmap回收自己。
- Bitmap是Drawable,Drawable不一定是Bitmap .就像拇指是指頭,但不是所有的指頭都是拇指一樣
- 
- 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))
- 
- 前言
- Android系統的體系結構
- Dalvik VM 和 JVM 的比較
- Android 打包應用程序并安裝的過程
- Android ADB工具
- Android應用開發
- Android UI相關知識總結
- Android 中window 、view、 Activity的關系
- Android應用界面
- Android中的drawable和bitmap
- AndroidUI組件adapterView及其子類和Adapter的關系
- Android四大組件
- Android 數據存儲
- SharedPreference
- Android應用的資源
- 數組資源
- 使用Drawable資源
- Material Design
- Android 進程和線程
- 進程
- 線程
- Android Application類的介紹
- 意圖(Intent)
- Intent 和 Intent 過濾器(Google官網介紹)
- Android中關于任務棧的總結
- 任務和返回棧(官網譯文)
- 總結
- Android應用安全現狀與解決方案
- Android 安全開發
- HTTPS
- 安卓 代碼混淆與打包
- 動態注入技術(hook技術)
- 一、什么是hook技術
- 二、常用的Hook 工具
- Xposed源碼剖析——概述
- Xposed源碼剖析——app_process作用詳解
- Xposed源碼剖析——Xposed初始化
- Xposed源碼剖析——hook具體實現
- 無需Root也能Hook?——Depoxsed框架演示
- 三、HookAndroid應用
- 四、Hook原生應用程序
- 五、Hook 檢測/修復
- Android 應用的逆向與加固保護技術
- OpenCV在Android中的開發
- Android高級開發進階
- 高級UI
- UI繪制流程及原理
- Android新布局ConstraintLayout約束布局
- 關鍵幀動畫
- 幀動畫共享元素變換
- Android異步消息處理機制完全解析,帶你從源碼的角度徹底理解
- Android中為什么主線程不會因為Looper.loop()里的死循環卡死?
- 為什么 Android 要采用 Binder 作為 IPC 機制?
- JVM 中一個線程的 Java 棧和寄存器中分別放的是什么?
- Android源碼的Binder權限是如何控制?
- 如何詳解 Activity 的生命周期?
- 為什么Android的Handler采用管道而不使用Binder?
- ThreadLocal,你真的懂了嗎?
- Android屏幕刷新機制