当前位置: 代码迷 >> Android >> Android 动画片使用注意事项
  详细解决方案

Android 动画片使用注意事项

热度:33   发布时间:2016-04-28 07:28:53.0
Android 动画使用注意事项

    今天在做开发的时候发现一个奇怪的问题,我使用Timer和Handler配合更新UI界面,Timer每隔一段时间执行一次,发送一次消息,然后Handler接受后更新UI,并在这里使用了动画效果。代码如下:

    

package com.example.handlerdemo;import java.util.Timer;import java.util.TimerTask;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.app.Activity;import android.view.Menu;import android.view.View;import android.view.animation.AccelerateInterpolator;import android.view.animation.TranslateAnimation;import android.widget.ImageView;import android.widget.TextView;public class MainActivity extends Activity {	private int animCount = -1;	Timer timer = new Timer(true);	Message message;	TextView tv_1, tv_2, tv_3, tv_4, tv_5;	private static Handler handler;	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		tv_1 = (TextView) this.findViewById(R.id.tv_1);		tv_2 = (TextView) this.findViewById(R.id.tv_2);		tv_3 = (TextView) this.findViewById(R.id.tv_3);		tv_4 = (TextView) this.findViewById(R.id.tv_4);		tv_5 = (TextView) this.findViewById(R.id.tv_5);		animPost();	}	private void animPost() {		// new Thread() {		// public void run() {		//		// // while (animCount < 5) {		// // try {		// // Message message = handler.obtainMessage();		// // message.arg1 = animCount;		// // handler.sendMessage(message);		// // animCount++;		// // Thread.sleep(2000);		// //		// // } catch (InterruptedException e) {		// // e.printStackTrace();		// // }		//		//		// }		// }.start();		handler = new Handler() {			public void handleMessage(Message msg) {				switch (msg.what) {				case 0:					if (animCount == 0) {						startAnimation(tv_1);					} else if (animCount == 1) {						startAnimation(tv_2);					} else if (animCount == 2) {						startAnimation(tv_3);					} else if (animCount == 3) {						startAnimation(tv_4);					} else if (animCount == 4) {						startAnimation(tv_5);					}					break;				}				super.handleMessage(msg);			}		};		TimerTask task = new TimerTask() {			@Override			public void run() {				// TODO Auto-generated method stub				if (message == null) {					message = new Message();				} else {					message = Message.obtain();				}				message.what = 0;				handler.sendMessage(message);				animCount = animCount + 1;				System.out.print(animCount);			}		};		timer.schedule(task, 0, 3000);	}	// 左右摆动	private void startAnimation(View paramView) {		TranslateAnimation localTranslateAnimation = new TranslateAnimation(2,				0.0F, 2, -0.05F, 1, 0.0F, 1, 0.0F);		localTranslateAnimation.setDuration(1000);		localTranslateAnimation.setInterpolator(new AccelerateInterpolator());		localTranslateAnimation.setRepeatCount(1);		// paramView.setAnimation(localTranslateAnimation);		// localTranslateAnimation.start();		paramView.startAnimation(localTranslateAnimation);//这个方式没有问题	}	@Override	public boolean onCreateOptionsMenu(Menu menu) {		// Inflate the menu; this adds items to the action bar if it is present.		getMenuInflater().inflate(R.menu.main, menu);		return true;	}}
    结果动画只是执行了一遍,开始我以为是使用Timer以及Handler逻辑的问题,换了几个方案都不行。最后无奈,试着从动画入手,改一下动画的启动方式。开始用的是

paramView.setAnimation(localTranslateAnimation);localTranslateAnimation.start();
    这个方法,这是组件设置动画效果,然后动画开始启动。当然还有组件启动动画的方式,我就试着换这种,发现问题解决了。那到底是什么原因导致的呢?搜了一下,网上没有这方面的资料。那只能去看api了。


    
     从图可知,startAnimmation是立即执行的。也就是说,我们调用了这个方法,动画马上就会执行。而setAnimmation的执行是需要两个先决条件的:

    1、动画要设置一个开始时间

    2、执行动画的组件的父视图在动画启动之前需要刷新界面。

    而我们就是因为没有满足这两个条件,所以出现了问题。

1楼zx1989989113小时前
您好,我刚才结合源代码发现有两点疑问想请教下:n1.你说的setAnimmation的执行是需要两个先决条件的的第二条貌似翻译有点问题吧,我的翻译是“组件在打算开始动画之前其父组件需要被刷新”n2.你之前说的那种所谓错误的动画启动方式应该是不满足第二个条件,你看源码就发现其实是满足第一个条件的。如果按照setAnimation()设置动画,其实去看startAnimation()原理发现下面这种方式也是正确的:nparamView.setAnimation(localTranslateAnimation);nlocalTranslateAnimation.start();nparamView.invalidate();nparamView.requestLayout();nn仅供参考,如有错误或者不对的可以多多交流哈。。。
Re: wangjinyu5013小时前
回复zx19899891n嗯,你说得对,昨天invalidate这个单词翻译错了,把我自己也弄迷糊了。看你一说恍然大悟,谢谢你的提醒,多多交流。
  相关解决方案