我学习Android都是结合源代码去学习,这样比较直观,非常清楚的看清效果,觉得很好,今天的学习源码是网上找的个GIF动画完美实现 源码 百度搜就知道很多下载的地方
这节学习的就是如何让一个GIF格式的文件在手机视图上显示出来,
要想做到这步
1.你需要准备好gif图片,放到drawable下面
2.你需要定义一个ImageView控件 来放置这个图片
3.在activity里面设置这个布局文件
那么问题就来了,我们前面学习的都是这样加载布局
setContentView(R.layout.main);等等这种方法,参数是一个布局文件资源索引
现在我们这里学习另外一种方式,setContentView(View view);
也就是说让我们这个界面以一种视图来加载,很显然我们就需要去定义一个View类。
我们自定义View类,我们在前面26个字母列表的实现中就说到了,想要去自己定义一个View类,必须去继承 android.view.View这个类,然后去重载
onDraw(Canvas canvas)函数就可以实现我们自定义的视图类
接下来看看代码是怎么实现的:
class CustomGifView extends View {
//构造函数 public CustomGifView(Context context) { super(context);//首先需要去构造基类
//这里去初始化你需要的成员变量等等 } //重载它的onDraw(Canvas canvas)函数 public void onDraw(Canvas canvas) { //TODO 处理你想要干的事,就是你想在画布上显示什么东西,这里都可以你自己去写,去设置 } } }
一.这个模式很简单,下面我们要处理的就是如何去实现动态GIF图像的播放了:
要想实现动态图片,我们必须要用到一个类,Movie,这个类就是在Android中解决GIF动画非常方便的一个选择
那么如果我们知道需要这个类,怎么去创建这个 Movie类呢,那么我们需要先去看看API关于这个类的描述了
public class
Movie extends Object
java.lang.Object | |
---|---|
↳ | android.graphics.Movie |
这么多public Methods方法,我们只需要看看 返回值是 Movie类型的函数就可以了
分别是下面的这几个:
1.static Movie decodeByteArray(byte[] data, int offset, int length)
很明白 它将一个byte[]类型的数组转换为一个Movie对象,从哪个位置开始,解析多长
2.static Movie decodeFile(String pathName)
它从将一个文件转换成Movie类
3.static Movie decodeStream(InputStream is)
它是将一个输入流转换成Movie类,
我们可以清楚的看到我们需要去怎么样创建一个Movie类了,方法1和方法3实质差别不大,因为我们可以将 输入流转变为byte[]类型的数组
这里我们使用第三个方法来创造这个类,
1.首先我们需要定义一个成员变量:
public Movie mMovie;
2.我们来初始化这个变量:
mMovie = Movie.decodeStream(getResources().openRawResource(R.drawable.animation));
有人在这里说,你直接给出这句代码我又看不懂了,那么好吧,我们来分析下怎么把一个文件转换成输入流
其实这个很简单,都是系统自定义的函数,我们按 快捷键 / Alt Eclipse立马会给你显示很多函数,那么我们只需要去找它的返回值就可以了,这样的语句就相当于自动生成了
那么我解释这里面用到的函数:
1.首先要找到这个文件
getResources() // 获得当前类所在的文件夹的名字 这个非常的常用,我们要获取一个文件夹下面的文件都用这个函数
Resources android. view. View.getResources()
public Resources getResources ()
Since: API Level 1
Returns the resources associated with this view.
Returns
- Resources object. 返回值是重点要关注的
2.找到文件之后,我们需要去打开这个文件,也就是操作这个文件,
操作文件肯定要用到open什么之类的,按快捷键 / Alt 肯定很多
openRawResource// 你如果看到一个Raw 要想到这个文件从资源文件索引找到的 ,重要的是关注它的返回值和参数
InputStream android. content. res. Resources.openRawResource( int id) throws NotFoundException
public InputStream openRawResource (int id)
Since: API Level 1
Open a data stream for reading a raw resource. This can only be used with resources whose value is the name of an asset files -- that is, it can be used to open drawable, sound, and raw resources; it will fail on string and color resources.
Parameters
id | The resource identifier to open, as generated by the appt tool. |
---|
Returns
- InputStream Access to the resource data.
Throws
Resources.NotFoundException | Throws NotFoundException if the given ID does not exist. |
---|
就这样我们完成了一个Movie类的构造过程了,也就是初始化了
二.当我们构造完成了Movie类,也就是将我们的GIF图片的信息给转存到Movie中去了,接下来我们要干什么呢?
肯定就是将这个信息展示给人看对不,也就是将这个信息画到视图上对不?对的
接下来我们就需要去处理 onDraw(Canvas canvas)这个函数了
在实现一个动画的时候,我们还需要掌握一些 知识
动画一般采用帧形式播放,这就决定我们需要去考虑播放的时间,每帧播放的长度,该帧播放完了之后,需要去更新视图对不对 也就是说这些都是需要在你的函数中去设置了
获得系统时间函数:
long now = android.os.SystemClock.uptimeMillis();
帧播放的开始时间:就是从系统当前的时间开始播放
if (mMovieStart == 0) { // first time //这个变量也需要在成员变量中定义处理 mMovieStart = now; }
开始播放之后,我们就需要设置每帧播放多长时间:
int dur = mMovie.duration(); if (dur == 0) { dur = 1000; }
每帧播放多长时间设置好了,我们就需要去算出该图片需要多少帧能够播放完:
int relTime = (int) ((now - mMovieStart) % dur);
然后把该帧显示出来就行了:
mMovie.setTime(relTime);
当这些设置都做完了,我们需要做的就是将这个Movie 显示到画布上去就行了,这步千万别忘记了,
mMovie.draw(canvas, 0, 0);//0.0表示图片在视图上显示的位置
显示完了,我们还要处理什么?什么呢?哈哈,视图需要更新啊,由于是动画,这帧放完了,赶紧放下帧,那么就涉及到视图的更新了,加一句代码就可以
invalidate();
至此 整个流程就清晰了,下面贴上系统的代码和展示图片:
代码语言:javascript复制import com.wust.gif.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
public Movie mMovie;
public long mMovieStart;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(new CustomGifView(this));
}
class CustomGifView extends View {
public CustomGifView(Context context) {
super(context);
mMovie = Movie.decodeStream(getResources().openRawResource(
R.drawable.animation));
}
public void onDraw(Canvas 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);
mMovie.setTime(relTime);
mMovie.draw(canvas, 0, 0);
invalidate();
}
}
}
}
很简单 什么布局文件都不要,只要这个类,配置到清单文件中去,然后运行就可以,当前你的drawable下面必须有这个GIF图片