前言
所谓手势,其实是指用户手指或触摸笔在触摸屏上的连续触碰行为,比如在屏幕上从左到右划出的一个动作,就是手势;再比如在屏幕上画出一个圆圈也是手势。手势这种连续的触碰会形成某个方向上的移动趋势,也会形成一个不规则的几何图形。Android对两种手势行为都提供了支持。对于第一种手势行为,Android提供了手势检测,并为手势检测提供了相应的监听器。对于第二种手势行为,Android允许开发者添加手势,并提供了相应的API识别用户手势。
手势检测
Android为手势检测提供了一个GestureDetector类,GestureDetector实例代表了一个手势检测器,创建GestrueDetector时需要传入一个DestureDetector.OnDestureListener实例,DestureDetector.OnDestureListener就是一个监听器,负责对用户的手势行为提供响应。GestureDetector.onDestureDetectorListener里包含的事件处理方法如下。 boolean onDown(MotionEvent e):当触碰事件按下时触发该方法。boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):当用户手指在触摸屏上“拖过”时触发该方法。其中velocityX、velocityY代表“拖过”动作在横向、纵向上的速度。abstract void onLongPress(MotionEvent e):当用户手指在屏幕上长按时触发该方法。boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):当用户手指在屏幕上“滚动”时触发该方法。void onShowPress(MotionEvent e):当用户手指在触摸屏上按下,而且还未移动和松开时触发该方法。boolean onSingleTapUp(MotionEvent e):用户手指在触摸屏上的轻击事件将会触发该方法。 关于GestureDetector.onGestureListener监听器里各方法的触发时机,仅从文字上表述总显得比较抽象而且难于理解,下面将以一个最简单的例子来让读者理解各方法的触发时机。
使用Android的手势检测只需两个步骤。
创建一个GestureDetector对象。创建该对象时必须实现一个GestureDetector.onGestureListener监听器实例。为应用程序的Activity(偶尔也可为特定组件)的TouchEvent事件绑定监听器,在事件处理中指定把Activity(或特定组件)上的TouchEvent事件交给GestureDetector处理。
经过上面两个步骤之后,Activity(或特定组件)上的TouchEvent事件就会交给GestureDetector处理,而GestureDetector就会检测是否触发了特定的手势动作。
下面的程序测试了用户的不同动作到底触发哪种手势动作。
package com.yzx.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener{
// 定义手势检测器实例
private GestureDetector gestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建手势检测器
gestureDetector = new GestureDetector(this, this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 将该Activity上的触碰事件交给GestureDetector处理
return gestureDetector.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
Toast.makeText(this,"onDown",Toast.LENGTH_SHORT).show();
return false;
}
@Override
public void onShowPress(MotionEvent e) {
Toast.makeText(this,"onShowPress",Toast.LENGTH_SHORT).show();
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
Toast.makeText(this,"onSingleTapUp",Toast.LENGTH_SHORT).show();
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Toast.makeText(this,"onScroll",Toast.LENGTH_SHORT).show();
return false;
}
@Override
public void onLongPress(MotionEvent e) {
Toast.makeText(this,"onLongPress",Toast.LENGTH_SHORT).show();
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Toast.makeText(this,"onFling",Toast.LENGTH_SHORT).show();
return false;
}
}
上面程序中的首先要创建一个GestureDetector对象,创建该对象时传入了this作为参数,这表明该Activity本身将会作为GestureDetector.onGestureListener监听器,所以该Activity实现了该接口,并实现了该接口里的全部方法。并把Activity上的TouchEvent交给GestureDetector处理。
实例:通过手势缩放图片代码如下:
package com.yzx.myapplication;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener{
// 定义手势检测器实例
private GestureDetector gestureDetector;
ImageView imageView;
// 初始的图片资源
Bitmap bitmap;
// 定义图片的宽高
int width, height;
// 控制图片缩放的matrix对象
Matrix matrix;
// 记录当前缩放比
float currentScale = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.show);
// 获取被缩放的源图片
bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
matrix = new Matrix();
// 获取位图宽
width = bitmap.getWidth();
// 获取位图高
height = bitmap.getHeight();
imageView.setImageBitmap(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));
// 创建手势检测器
gestureDetector = new GestureDetector(this, this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 将该Activity上的触碰事件交给GestureDetector处理
return gestureDetector.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
velocityX = velocityX > 4000 ? 4000 : velocityX;
velocityX = velocityX < -4000 ? -4000 : velocityX;
// 根据手势的速度来计算缩放比,如果velocityX>0,放大图像,否则缩小图像
currentScale += currentScale * velocityX / 4000.0f;
// 保证currentScale不会等于0
currentScale = currentScale > 0.01 ? currentScale : 0.01f;
// 重置Matrix
matrix.reset();
// 缩放Matrix
matrix.setScale(currentScale,currentScale,160,200);
// 如果图片还未回收,先强制回收该图片
BitmapDrawable tmp = (BitmapDrawable) imageView.getDrawable();
if(!tmp.getBitmap().isRecycled()) {
tmp.getBitmap().recycle();
}
// 根据原始位图和Matrix创建新图片
Bitmap bitmap1 = Bitmap.createBitmap(bitmap,0,0,width,height,matrix,true);
// 显示新的位图
imageView.setImageBitmap(bitmap1);
return true;
}
}