Android提供了一个自定义的2D图形库来绘制图像和图像.在android.graphics.drawable包中你就可以找到这些用于2维绘画的通用类.

本文讨论使用Drawable对象来作画的基础知识以及如何使用一对Drawable类的派生类.
Drawable是通常指的那种可以作画的东西的抽象.你将发现Drawable类扩展出了很多特定的可绘图形类,包括BitmapDrawable,ShapeDrawable,PictureDrawable,LayerDrawable,等等.当然,你也可以从它们派生出你自己的类来定义你自己的Drawable对象,当然以你独有的方式来表现.

有三种方法来定义并实例化一个Drawable:使用一个保存在你的项目资源中的图像;使用一个定义了Drawable属性的XML文件;或使用普通的类对象构造方式.下面,我们将讨论前两种方式(类对象构就是new出一个对象,傻子都知道,所以不说了).

从资源中的图像创建

添加图形到你的应用的一个简单的方式是从你的项目资源中引用一个图像文件.支持的文件格式有PNG(首选),JPG (可接受)和GIF(不推荐).此技术优先用于程序图标,logo,或其它图形,比如用于游戏中的.
要使用一个图像资源,只需把你的文件添加到项目的res/drawable/文件夹下.从这里,你可以在你的代码或XMLlayout中引用它.不论从哪里引用,推荐使用一个资源ID,它是不带扩展名的文件名(例如,my_image.png的ID是my_image).
注:图像资源放在res/drawable/下,可能会在构建过程中自动被aapt工具无损压缩以进行优化.例如,一个不需要超过256种颜色的真彩色PNG可能被转换成一个带有调色板的8位PNG.这将造成保持图像质量不变的情况下,占用更少的内存.所以要注意放在这个文件夹下的图像在构建期间可能会改变.如果你想把一个图像作为比特流读入以转换成一个bitmap,那么应把你的图象放在res/raw/文件夹下,在这里他们不会被优化.

代码例子

下面的代码片段演示了如何使用drawable中的资源创建一个ImageView然后把它添加到layout:

[java] LinearLayout mLinearLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Create a LinearLayout in which to add the ImageView
mLinearLayout = new LinearLayout(this);

// Instantiate an ImageView and define its properties
ImageView i = new ImageView(this);
i.setImageResource(R.drawable.my_image);
i.setAdjustViewBounds(true); // 设置ImageView与Drawable的宽高比相同
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));

// Add the ImageView to the layout and set the layout as the content view
mLinearLayout.addView(i);
setContentView(mLinearLayout);
}
LinearLayout mLinearLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Create a LinearLayout in which to add the ImageView
mLinearLayout = new LinearLayout(this);

// Instantiate an ImageView and define its properties
ImageView i = new ImageView(this);
i.setImageResource(R.drawable.my_image);
i.setAdjustViewBounds(true); // 设置ImageView与Drawable的宽高比相同
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));

// Add the ImageView to the layout and set the layout as the content view
mLinearLayout.addView(i);
setContentView(mLinearLayout);
}

有时,你可能想把你的图像资源做为Drawable对象处理.要这样做,需从资源创建一个Drawable对象:

[java] Resources res = mContext.getResources();
Drawable myImage = res.getDrawable(R.drawable.my_image);
Resources res = mContext.getResources();
Drawable myImage = res.getDrawable(R.drawable.my_image);
注:不管有多少不同的对象实例化它,你项目中的每个唯一的资源只能保持一种状态.例如,如果你从同一个图像资源实例化了两个Drawable对象,然后用其中一个改变了一个属性(比如alpha),那么它将也影响到另一个.所以当处理一个图像资源的多个实例时,你应该执行一个过渡动画,而不是直接转换Drawable.
XML例子

下面的XML片段演示了如何在XMLlayout中添加一个资源Drawable到一个ImageView.

[html] <ImageView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:tint=”#55ff0000″
android:src=”@drawable/my_image”/>
<ImageView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:tint=”#55ff0000″
android:src=”@drawable/my_image”/>

从资源XML创建

现在,你应该熟悉了andriod下开发用户界面的原则.所以,也了解了在XML中定义对象的强大和灵活性.此理念贯穿了Views到Drawables.如果你想创建一个Drawable对象,而它最初不是依赖于你应用代码所定义的变量或userinteraction,那么最好就去XML中定义这个Drawable.即使你希望你的Drawable在用户使用过程中也可改变它的属性,你也应该考虑在XML中定义对象,因为在它初始化后你也可以改变它的属性.
一旦你在你的XML中定义了Drawable,就应把文件保存到项目的res/drawable/文件夹下.然后,通过调用Resources.getDrawable()方法获取并实例化这个对象,把你的XML文件的资源ID传给这个函数(见下面的例子).

任何支持inflate()方法的Drawable的子类都可以被定义在XML中并且被应用所实例化.每个支持XMLinflation的Drawable利用了特定的XML属性来帮助定义对象的属性(见类的的参考文档来了解它们是什么).见每个Drawable的子类的类描述文档来了解如何在XML中定义.

例子

下面是一些定义TransitionDrawable的XML:

[html] <transition xmlns:android=”http://schemas.android.com/apk/res/android“>
<item android:drawable=”@drawable/image_expand”>
<item android:drawable=”@drawable/image_collapse”>
</transition>
<transition xmlns:android=”http://schemas.android.com/apk/res/android“>
<item android:drawable=”@drawable/image_expand”>
<item android:drawable=”@drawable/image_collapse”>
</transition>

此XML保存在res/drawable/expand_collapse.xml,下面的代码将实例化TransitionDrawable并且把它设置为一个ImageView的内容:
[java] Resources res = mContext.getResources();
TransitionDrawable transition = (TransitionDrawable)
res.getDrawable(R.drawable.expand_collapse);
ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);
Resources res = mContext.getResources();
TransitionDrawable transition = (TransitionDrawable)
res.getDrawable(R.drawable.expand_collapse);
ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);
然后这个转换就可以通过以下设置运行一秒钟:
transition.startTransition(1000);