Movie来播放GIF动画

摘自

DroidKe

Just Another Android Blog

播放GIF出现的花屏问题

Movie来播放gif动画时,开始用android的SDK自带的ApiDemos里的gif图片是正常的,后来发现用上自己的gif图片就出现了花屏的问题。

也许两张gif图片之间有什么设置差别造成的呢?于是我用Adobe ImageReady打开了能正常显示的和出现花屏的gif图片进行对比。
结果找到来解决问题的方法(也许还有别的更好的方法)。
如下图:

右击动画帧,然后选择“恢复为背景”。

用Movie来播放GIF动画

目前android.graphics.Movie类在SDK文档中还没有任何的说明。
Movie类是可以用来播放gif动画,跟电影的原理一样都是通过播放连续的帧,利用视觉暂留得到运动的效果。这倒使我想到了AnimationDrawable类,这两者看起来差不多,于是尝试用Movie类来播放AnimationDrawable定义的动画,失败了。

1,原理

通过不停的重新绘制来换帧。

2,方法说明

decodeByteArray(byte[] data, int offset, int length)
decodeFile(String pathName)
decodeStream(InputStream is)
三种不同的静态方法来获取Movie对象。三种方式的原理其实都一样,都是读入字节流来解码创建Movie对象。decodeByteArray是从一个已经存在的字节数组中创建,decodeFile是从一个文件读入字节流来创建。

draw(Canvas canvas, float x, float y)
draw(Canvas canvas, float x, float y, Paint paint)
绘制动画帧。
它们其实还是调用Canvas的drawBitmap来绘制帧的。

duration()
动画持续的时间,也就是完成一次动画播放的时间。

isOpaque()
是不是不透明

setTime(int relativeMilliseconds)
设置相对本次播放第一帧时间,根据这个时间来决定显示第几帧。

例如:
int relTime=(int)((now – moviestart)%movie.duration());
now:系统当前时刻
moviestart:动画开始的时间
movie.duration:动画持续的时间,也就是完成一次动画的时间
注意这是取余操作,这才能算出当前这次重复播放的第一帧的时间。

height() 高
width() 宽

3,实例

public class Main extends Activity {
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new SampleView(this));
    }
 
    private static class SampleView extends View {
    	private Movie mMovie;
    	private long mStart=0;
    	private int relTime;
         public SampleView(Context context) {
             super(context);
             mMovie = Movie.decodeStream(context.getResources().openRawResource(R.drawable.pig));
         }
 
         @Override protected void onDraw(Canvas canvas) {
        	 long now=android.os.SystemClock.uptimeMillis();
        	 if(mStart==0) mStart = now;
        	 int dur=mMovie.duration();
        	 if(dur==0) dur=1000;
        	 relTime=(int)((now-mStart)%dur);
 
        	 mMovie.setTime(relTime);
        	 canvas.drawColor(Color.WHITE);
        	 mMovie.draw(canvas, 0,0);
        	 this.invalidate();
             }
         }
}

对Animation的理解

对android的Animation的初级理解,Moandroid的下面三篇文章已经讲解的很清楚了。
http://www.moandroid.com/?p=790
http://www.moandroid.com/?p=808
http://www.moandroid.com/?p=812

1,android的动画分为两种:Tween Animation和Frame Animation。
这个两种动画的原理也是不相同的,他们的包在SDK中的位置也是不一样。Tween动画的包在android.view.animation下,Frame动画的包在android.graphics.drawable下。

2,这两种动画的不同在于:
Frame动画是对预先设置好的图片进行依次显示,以产生动画效果,就象电影那样。
Tween动画则是要把它作用于某个对象上,如view组件,drawable。例如有个Button,想让它产生转换位置的动画效果,那么就要创建一个TranslateAnimation对象,然后把它作用于这个Button上。

3,那么TranslateAnimation是如何才能作用与Button上呢?
View对象都有一个setAnimation方法就是来和动画关联起来产生动画效果。那么如果才能让drawable也产生动画呢,drawable可没有setAnimation方法来调用的。
android的View组件其实也是调用android.graphics.*包里的相关工具绘制出来的,也就是所View产生动画的原理同样可以让drawable产生动画。

4,Tween动画的原理
View组件是由Canvas来绘制出来的。
Canvas类包含一个Martix,在绘制时会先进行一次矩阵运算,把运算的的结果显示在Canvas上。这时图片就产生了变动,图形变换通过仿射矩阵实现。图形变换是图形学中的基本知识。简单来说就是,每种变换都是一次矩阵运算。
Animation类有有个getTransformation(long currentTime, Transformation outTransformation)方法来获取此动画当前时刻的Transformation,它记录了仿射矩阵 Matrix,动画每触发一次,会对原来的矩阵做一次运算。然后通过Transformation的getMatrix()方法把此Martix给提取出来。
然后让Cavnas运行此Martix,通过Canvas的concat(Matrix matrix)方法来替换当前的martix。
到这里View按Animation的变换了一次,接下来就是要不停的从Animation中获取Martix(如何变换的信息),Canvas不断的改变,就产生的动画效果。

5,让drawable产生Tween动画的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class Main extends Activity {
	private Animation ani ;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new myView(this));
    }
 
   private class myView extends View
   { 
	   private  Drawable da;
	   private  ScaleAnimation sa;
	   private int i=0;
	public myView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		//创建drawable
         da =getResources().getDrawable(R.drawable.google);
         da.setBounds(0, 0,da.getIntrinsicWidth(), da.getIntrinsicHeight());
 
         //创建一个Animation,并设置。
         sa = new   ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
         sa.setDuration(3000);
         sa.setRepeatCount(1);
         sa.setRepeatMode(2);
         sa.startNow();
	}
 
	@Override
	protected void onDraw(Canvas canvas)
	{        
               //获取Transformation
	        Transformation tf = new Transformation();
	        sa.getTransformation(AnimationUtils.currentAnimationTimeMillis(), tf);
 
	        canvas.drawColor(Color.BLACK);
                //获取Matrix并设置到canvas
	        canvas.concat(tf.getMatrix());        
 
	        da.draw(canvas);   
                //这个是来设置不停的获取Martix来重绘
	        invalidate();
	}
 }
}

有关Intent的putExtra

我们可以通过putExtra方法向Intent中添加数据。

在Intent类中有很多重载的putExtra方法。在android中Intent是通过Bundle类型来传递数据的,这些重载的方法获取到参数后也是转换成Bundle类型后才传输的。

例如其中一个方法的实现:

public Intent putExtra(String name, byte value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putByte(name, value);
return this;
}
如果想传多组值,可以多次调用putExtra方法:
intent1.putExtra(“name”,”liu”);
intent1.putExtra(“city”,”beijing”);
当然可以直接使用Bundle容器,然后调用 putExtras(Bundle  extras)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值