Android 2D Graphics
1 Drawable Drawable
是一个通用的抽象类,它的目的是告诉你什么东西是可以画的。你会发现基于Drawable类扩展 出各种绘图的类包括:BitmapDrawable ShapeDrawable PictureDrawable LayerDrawable,当然你 可以继承它来创建你自己的绘图类. 有三种方法可以定义和实例化一个Drawable,保存一个图片到你工程资源中,使用XML文件来描述 Drawable属性或者用一个正常的类去构造。下面我们将讨论两种技术(对一个有开发经验的开发者来说构 造并不是最新的技术)
1.1 从资源图像文件中创建 一个比较简单的方法是添加一个图片到你的程序中,然后通过资源文件引用这个文件,支持的文件类型 有PNG(首选的) JPG(可接受的)GIF(不建议),显然这种对于显示应用程序的图标跟来说是首选的方 法,也可以用来显示LOGO,其余的图片可以用在例如游戏中。 把一个图片资源,添加你的文件到你工程中res/drawable/目录中去,从这里,你就可以引用它到你的代码 或你的XML布局中,另一种方法,引用它也可以用资源编号,比如你选择一个文件只要去掉后缀就可以了 (例如:my_image.png 引用它是就是my_image)
1.2 从XML文件中创建 到如今,你应该比较熟悉按Android的原则去开发一个用户接口,因此,你也应该理解了定义一个XML文 件对于对象的作用与灵活的重要性。这个理念无数次用于Drawables 如果你想创建一个Drawable对象,而这个对象并不依赖于变量或用户的交换,把它定义到XML中去应该 是一个不错的方法。即使你期望在你的应用程序中改变其属性来增加用户体验。你应该考虑把对象放入 XML中,因为你可以随时修改其属性。 当你在你的XML中定义了一个Drawable,保存这个XML文件到你工程目录下res/drawable目录中,然 后通过调用Resource.getDrawable()来检索并实例化,传递给它XML文件中的资源ID号。 任何Drawable的子类都支持inflate这个方法,这个方法会通过XML来实例化你的程序。任何Drawable 都支持XML的扩展来利用特殊的XML属性来帮助定义对象的属性,可以查看任何Drawable子类文档来看 如何定义XML文件 下面的XML定义了TransitionDrawable:
<item android:drawable="@drawable/image_expand">
<item android:drawable="@drawable/image_collapse">
</transition>
2 ShapeDrawable
private ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
}
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
ShapeDrawable类(像很多其他Drawable类型在android.graphics.drawable包)允许你定义drawable公共方法的各种属性。有些属性你可以需要调整,包括,透明度,颜色过滤,不透明度,颜色。
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:text="Tiny"
android:textSize="8sp"
android:background="@drawable/my_button_background"/>
<Button id="@+id/big"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:text="Biiiiiiig text!"
android:textSize="30sp"
android:background="@drawable/my_button_background"/>
4 Tween Animation
一个tween动画将对视图对象中的内容进行一系列简单的转换(位置,大小,旋转,透明性)。如果你有 一个文本视图对象,你可以移动它,旋转它,让它变大或让它变小,如果文字下面还有背景图像,背景 图像也会随着文件进行转换。Animation package 提供了所有的类来供tween 动画使用。 Tween 动画定义了一个动画指令的队列,定义可以使用XML也可以再Android的代码中,像定义布局一 样,我们建议使用XML来定义,因为它具备的阅读性,重用性,可以交换性大大超过了硬编码。在下面 的例子中,我们使用XML(参考AnimationSet 类或者其它的动画类来学习如何在代码中定义) 动画的指令定义了你想要发生什么样的转换,当他们发生了,应该执行多长时间,转换可以是连续的也 可以使同时的。例如,你让文本内容从左边移动到右边,然后旋转180度,或者在移动的过程中同时旋 转,没个转换需要设置一些特殊的参数(开始和结束的大小尺寸的大小变化,开始和结束的旋转角度等 等,也可以设置些基本的参数(例如,开始时间与周期),如果让几个转换同时发生,可以给它们设置 相同的开始时间,如果按序列的话,计算开始时间加上其周期。 动画的XML文件还是在你工程中res/anim目录,这个文件必须包含一个根元素,可以使<alpha> <scale> <translate> <rotate> 插值元素或者是把上面的元素都放入<set>元素组中,默认情况下,所以的动画指令都是同时发生的, 为了让他们按序列发生,需要设置一个特殊的属性startOffset,下面的例子会演示。 下面的ApiDemos XML文件定义了视图对象的伸缩功能,同时发生旋转 。
android:interpolator="@android:anim/
accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" />
<set android:interpolator="@android:anim/decelerate_interpolator">
<scale
android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
android:fillBefore="false" />
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400" />
</set></set>
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this,
R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
5 Frame Animation
虽然你可以在代码中定义帧动画,可以使用AnimationDrawable类的API.,它是非常简单通过XML文件 列出动画中的所有帧,像上面的动画tween,这种类别动画的XML文件放入工程中的res/anim目录。既 然这样,指令按照周期去执行每帧动画。 在XML文件包含一个<animation-list>根节点元素和好几个子节点<item>来定义每帧。一个资源分别定 义了帧的名字与帧的持续时间。下面为范例:
<item android:drawable="@drawable/rocket_thrust1"
android:duration="200" />
<item android:drawable="@drawable/rocket_thrust2"
android:duration="200" />
<item android:drawable="@drawable/rocket_thrust3"
android:duration="200" />
</animation-list>
这个动画播放三个帧动画,通过设置android:oneshot属性为true,它将会在最后一帧停下来,如果设置 为false这个动画将循环播放。这个文件保存到工程目录res/anim目录下为rocket_thrust.xml,你也 可以添加一个背景图片到视图中,然后开始播放。下面为范例:
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.anim.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rocketAnimation.start();
return true;
}
return super.onTouchEvent(event);
}
一个比较需要特别注意的是,在AnimationDrawable调用onCreate()过程中不能调用start(),这是因 为AnimationDrawable不能在不完全的窗口上运行,如果你想立即播放动画,没有必要的交互,你可以 再onWindowFocusChanged()方法中调用它。这样它将成为窗口焦点。
完毕。^_^