浅谈Android动画中点击事件的捕捉

最近开发了一款软件,其中有需要点击执行动画中的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;
	}

}
运行结果:

现在点击显示区域就被转移到了控件上。

实现的主要思想是:计算平移位置,然后通过坐标转换映射到控件实际位置上,就可以判断点击是否触发了。

希望本文对您有用,转载请注明!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值