Android APIDemos 研读之一:android.graphics.Movie
2013-10-17 15:12
435 查看
原创:http://blog.csdn.net/sharetop/article/details/5268419
如何在Android中显示GIF动画,有很多方法,比如可以使用J2ME平台上那个解码工具类,纯java的,拿来即可。
但是其实Android还是为我们提供了一个更为方便的工具:android.graphics.Movie。
参考例子在ApiDemos中的BitmapDecode中。
下面我只是简单地用它来实现一个自己的GIFView,以方便在各种需要使用GIF动画的场合使用。
为了简单,我让GIFView extends ImageView罢了。它在布局中的描述如下:
[xhtml] view
plaincopy
<cn.sharetop.android.view.GIFView
android:id="@+id/gif"
android:layout_gravity="center_horizontal"
android:layout_width="278px"
android:layout_height="183px"
android:scaleType="fitXY"
app:gif="@drawable/a"
android:src="@drawable/a"
/>
与ImageView唯一的区别在于我加了一个gif属性,与src属性的值是一样的。不过它们需要同时存在,不可省略其中之一(后面我会说明为什么)。
注意因为gif属性,所以别忘了那个attr.xml中也要加上:
[xhtml] view
plaincopy
<resources>
<declare-styleable name="GIFView">
<attr name="gif" format="reference" />
</declare-styleable>
</resources>
然后是代码,没几行的:
[java] view
plaincopy
public class GIFView extends ImageView {
private static final String TAG="GIFView";
private Movie mMovie;
private long mMovieStart;
//此处省略几个构造函数
//......
//主要的构造函数
public GIFView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
mMovie=null;
mMovieStart=0;
//从描述文件中读出gif的值,创建出Movie实例
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.GIFView, defStyle, 0);
int srcID=a.getResourceId(R.styleable.GIFView_gif, 0);
if(srcID>0){
InputStream is = context.getResources().openRawResource(srcID);
mMovie = Movie.decodeStream(is);
}
a.recycle();
}
//主要的工作是重载onDraw
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
//super.onDraw(canvas);
//当前时间
long now = android.os.SystemClock.uptimeMillis();
//如果第一帧,记录起始时间
if (mMovieStart == 0) { // first time
mMovieStart = now;
}
if (mMovie != null) {
//取出动画的时长
int dur = mMovie.duration();
if (dur == 0) {
dur = 1000;
}
//算出需要显示第几帧
int relTime = (int)((now - mMovieStart) % dur);
//Log.d(TAG,"---onDraw..."+mMovie.toString()+",,,,"+relTime);
//设置要显示的帧,绘制即可
mMovie.setTime(relTime);
mMovie.draw(canvas,0,0);
invalidate();
}
}
}
代码中已有注释,就不多说了。我的理解是Movie其实管理着GIF动画中的多个帧,只需要通过 setTime() 一下就可以让它在draw()的时候绘出相应的那帧图像。
通过当前时间与duration之间的换算关系,是很容易实现GIF动起来的效果。
最后,说一下为什么src与gif要同时存在了,因为我这个GIFView很简单,没有自己去onMeasure,所以要借助src让ImageView去计算它的尺寸和布局之类的事情。
只是在onDraw的时候,不显示src而已。
如果感兴趣的同学可以自己完善这个GIFView,比如以下两点:
1. 只需要一个gif属性,不要src了,或者直接使用src属性?
2. 如果在xml中没有指定gif/src的值,增加一些方法让用户可以通过代码设置gif和src的值
[补充]
刚才又觉得这段代码有修正的必要:
1. 关于如何直接使用src这个属性,仍是修改attr.xml中,这样即可:
[xhtml] view
plaincopy
<resources>
<declare-styleable name="GIFView">
<attr name="android:src" />
</declare-styleable>
</resources>
然后在main.xml中就不再需要gif这个属性,直接用src就可以了。
如何在Android中显示GIF动画,有很多方法,比如可以使用J2ME平台上那个解码工具类,纯java的,拿来即可。
但是其实Android还是为我们提供了一个更为方便的工具:android.graphics.Movie。
参考例子在ApiDemos中的BitmapDecode中。
下面我只是简单地用它来实现一个自己的GIFView,以方便在各种需要使用GIF动画的场合使用。
为了简单,我让GIFView extends ImageView罢了。它在布局中的描述如下:
[xhtml] view
plaincopy
<cn.sharetop.android.view.GIFView
android:id="@+id/gif"
android:layout_gravity="center_horizontal"
android:layout_width="278px"
android:layout_height="183px"
android:scaleType="fitXY"
app:gif="@drawable/a"
android:src="@drawable/a"
/>
与ImageView唯一的区别在于我加了一个gif属性,与src属性的值是一样的。不过它们需要同时存在,不可省略其中之一(后面我会说明为什么)。
注意因为gif属性,所以别忘了那个attr.xml中也要加上:
[xhtml] view
plaincopy
<resources>
<declare-styleable name="GIFView">
<attr name="gif" format="reference" />
</declare-styleable>
</resources>
然后是代码,没几行的:
[java] view
plaincopy
public class GIFView extends ImageView {
private static final String TAG="GIFView";
private Movie mMovie;
private long mMovieStart;
//此处省略几个构造函数
//......
//主要的构造函数
public GIFView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
mMovie=null;
mMovieStart=0;
//从描述文件中读出gif的值,创建出Movie实例
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.GIFView, defStyle, 0);
int srcID=a.getResourceId(R.styleable.GIFView_gif, 0);
if(srcID>0){
InputStream is = context.getResources().openRawResource(srcID);
mMovie = Movie.decodeStream(is);
}
a.recycle();
}
//主要的工作是重载onDraw
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
//super.onDraw(canvas);
//当前时间
long now = android.os.SystemClock.uptimeMillis();
//如果第一帧,记录起始时间
if (mMovieStart == 0) { // first time
mMovieStart = now;
}
if (mMovie != null) {
//取出动画的时长
int dur = mMovie.duration();
if (dur == 0) {
dur = 1000;
}
//算出需要显示第几帧
int relTime = (int)((now - mMovieStart) % dur);
//Log.d(TAG,"---onDraw..."+mMovie.toString()+",,,,"+relTime);
//设置要显示的帧,绘制即可
mMovie.setTime(relTime);
mMovie.draw(canvas,0,0);
invalidate();
}
}
}
代码中已有注释,就不多说了。我的理解是Movie其实管理着GIF动画中的多个帧,只需要通过 setTime() 一下就可以让它在draw()的时候绘出相应的那帧图像。
通过当前时间与duration之间的换算关系,是很容易实现GIF动起来的效果。
最后,说一下为什么src与gif要同时存在了,因为我这个GIFView很简单,没有自己去onMeasure,所以要借助src让ImageView去计算它的尺寸和布局之类的事情。
只是在onDraw的时候,不显示src而已。
如果感兴趣的同学可以自己完善这个GIFView,比如以下两点:
1. 只需要一个gif属性,不要src了,或者直接使用src属性?
2. 如果在xml中没有指定gif/src的值,增加一些方法让用户可以通过代码设置gif和src的值
[补充]
刚才又觉得这段代码有修正的必要:
1. 关于如何直接使用src这个属性,仍是修改attr.xml中,这样即可:
[xhtml] view
plaincopy
<resources>
<declare-styleable name="GIFView">
<attr name="android:src" />
</declare-styleable>
</resources>
然后在main.xml中就不再需要gif这个属性,直接用src就可以了。
相关文章推荐
- Android APIDemos 研读之一:android.graphics.Movie
- Android APIDemos 研读之二:android.graphics.Camera
- Android APIDemos 研读之二:android.graphics.Camera
- Android ApiDemos示例解析(78):Graphics->ScaleToFit
- Android ApiDemos示例解析(85):Graphics->Vertices
- Android ApiDemos示例解析(201):Graphics->OpenGL ES->Compressed Texture
- Android ApiDemos示例解析(60):Graphics->ColorMatrix
- Android ApiDemos示例解析(63):Graphics->Density
- Android ApiDemos示例解析(67):Graphics->Layers
- Android ApiDemos示例解析(205):Graphics->OpenGL ES->Translucent GLSurfaceView
- Android ApiDemos 学习 Graphics->SensorTest
- Android ApiDemos示例解析(200):Graphics->OpenGL ES->Textured Triangle
- Android ApiDemos示例解析(79):Graphics->SensorTest
- Android ApiDemos示例解析(81):Graphics->Text Align
- Android ApiDemos示例解析(202):Graphics->OpenGL ES->Cube Map
- Android ApiDemos示例解析:Graphics->Layers
- Android ApiDemos示例解析(203):Graphics->OpenGL ES->GLSurfaceView
- Android ApiDemos示例解析(68):Graphics->MeasureText
- Android ApiDemos示例解析(82):Graphics->TouchPaint
- android.graphics.Movie