最近开发了一款软件,其中有需要点击执行动画中的View。很多人最初看到这种问题,可能会对此嗤之以鼻,认为给View加上事件监听就可以轻松解决问题了。但事情没有这么简单,因为Android控件做动画时并没有移动其位置,移动的仅是显示区域,如果有空,我会写一篇Blog详述此中原由。
对此问题的解决方案我将使用一个ImageView来讲解。首先,我们来看一下最初的状态。(红色箭头为鼠标点击位置)
package com.example.testtranslatelistener;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.Toast;
/**
*
*
* @author 孔令辉
* @date 2013-11-6
*
*/
public class MainActivity2 extends Activity {
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = getLayoutInflater().inflate(R.layout.activity_main, null,
true);
imageView = (ImageView) view.findViewById(R.id.testImage);
imageView.setOnTouchListener(onTouchListener);
this.setContentView(view);
}
private OnTouchListener onTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(MainActivity2.this, "isTouch: true", 0).show();
return false;
}
};
}
从上图我们可以看到当没有动画时触摸事件被触发。下面我们来看一下添加动画之后的效果:
代码:
package com.example.testtranslatelistener;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.Toast;
/**
*
*
* @author 孔令辉
* @date 2013-11-6
*
*/
public class MainActivity2 extends Activity {
private ImageView imageView;
private static TranslateAnimation animation = new TranslateAnimation(220,
0, 0, 0);;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = getLayoutInflater().inflate(R.layout.activity_main, null,
true);
imageView = (ImageView) view.findViewById(R.id.testImage);
imageView.setOnTouchListener(onTouchListener);
this.setContentView(view);
/*
* 初始化动画
*/
animation.setDuration(4000);
animation.setRepeatCount(Animation.INFINITE);
animation.setInterpolator(new LinearInterpolator());
imageView.setAnimation(animation);
imageView.startAnimation(animation);
}
private OnTouchListener onTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(MainActivity2.this, "isTouch: true", 0).show();
return false;
}
};
}
由上面两图可以看出,动画只是移动View的表象,而其实际位置并未改变,所以点击事件无效。那么我们怎么来捕捉移动过程中的点击呢?来看一下代码:
package edu.pku.kong.testtranslatelistener;
import java.util.Date;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.Toast;
/**
*
*
* @author 孔令辉
* @date 2013-11-7
*
*/
public class MainActivity extends Activity {
private ImageView imageView;
private int l;
private int r;
private int t;
private int b;
private static TranslateAnimation animation = new TranslateAnimation(220,
0, 0, 0);;
private Date date;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = getLayoutInflater().inflate(R.layout.activity_main, null,
true);
imageView = (ImageView) view.findViewById(R.id.testImage);
view.setOnTouchListener(onTouchListener);
this.setContentView(view);
animation.setDuration(4000);
animation.setRepeatCount(Animation.INFINITE);
animation.setInterpolator(new LinearInterpolator());
imageView.setAnimation(animation);
date = new Date();
imageView.startAnimation(animation);
}
private OnTouchListener onTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
/**
* Projection 用于将屏幕坐标转换为地理位置坐标
*/
float dx = event.getX();
float dy = event.getY();
l = imageView.getLeft();
t = imageView.getTop();
r = imageView.getRight();
b = imageView.getBottom();
Date time = new Date();
long a = time.getTime() - date.getTime();
boolean isTouch = isTouch(l, r, t, b, dx, dy, (int)a);
Toast.makeText(MainActivity.this, "isTouch:" + isTouch, 0).show();
return false;
}
};
private boolean isTouch(int l, int r, int t, int b, float dx, float dy,
int time) {
float scale = ((float)(time % 4000))/4000;
dx = dx - (int)((220 * (1-scale)) + 0.5 * (r - l));
return isTouch(l, r, t, b, dx, dy);
}
private boolean isTouch(int l, int r, int t, int b, float dx, float dy) {
if (l < dx && dx < r && t < dy && dy < b) {
return true;
}
return false;
}
}
运行结果:
现在点击显示区域就被转移到了控件上。
实现的主要思想是:计算平移位置,然后通过坐标转换映射到控件实际位置上,就可以判断点击是否触发了。
希望本文对您有用,转载请注明!