View绘制Drawable原理分析记录
Drawable是Android开发中的通用可绘制对象,View类默认针对Drawable进行一些必要的绘制,如背景,此文旨在记录分析View绘制Drawable时的关键细节
1.XML布局文件的Background
通常,我们在XML文件中设置View的background如下:
android:background="@drawable/drawable_bg"/*设置其他Drawable背景*/
android:background="#ff124a54"/*设置颜色背景*/
在展开阐述之前,我们先明确一下,android:background属性值在实际操作中都会实例化为Drawable,参考官方文档,常用的属性值与Drawable对象关系如下:
- “#ffffffff”=>ColorDrawable
- “@drawable/shape_bg”=>GradientDrawable(假设shape_bg.xml文件为顶层为shape标签)
- “@drawable/bmp_bg”=>BitmapDrawable(假设bmp_bg为.png/.jpg/.bmp文件)
- “@drawable/9patch_bg”=>NinePatchDrawable(假设9patch_bg为.9.png文件)
2.Drawable的ConstantState
2.1什么是ConstantState
如果把Drawable比作一个绘制容器,那么ConstantState就是容器中真正的内容,Drawable的源码如下:
/**
* This abstract class is used by {@link Drawable}s to store shared constant state and data
* between Drawables. {@link BitmapDrawable}s created from the same resource will for instance
* share a unique bitmap stored in their ConstantState.
*
* <p>
* {@link #newDrawable(Resources)} can be used as a factory to create new Drawable instances
* from this ConstantState.
* </p>
*
* Use {@link Drawable#getConstantState()} to retrieve the ConstantState of a Drawable. Calling
* {@link Drawable#mutate()} on a Drawable should typically create a new ConstantState for that
* Drawable.
*/
public static abstract class ConstantState {
/**
* Create a new drawable without supplying resources the caller
* is running in. Note that using this means the density-dependent
* drawables (like bitmaps) will not be able to update their target
* density correctly. One should use {@link #newDrawable(Resources)}
* instead to provide a resource.
*/
public abstract Drawable newDrawable();
/**
* Create a new Drawable instance from its constant state. This
* must be implemented for drawables that change based on the target
* density of their caller (that is depending on whether it is
* in compatibility mode).
*/
public Drawable newDrawable(Resources res) {
return newDrawable();
}
/**
* Return a bit mask of configuration changes that will impact
* this drawable (and thus require completely reloading it).
*/
public abstract