一、给view设置手势操作有2种方式:
1、自定义view并实现其ontouchevent,然后定制自己的监听手势
2、通过GestureDetector和touchlistener配合使用
主要介绍第二种方法:
GestureDetector是android提供的手势操作类
用法:GestureDetector g = new GestureDetector(Context contenxt,GestureListener gestureListener);
GestureListener 是GestureDetector 内部封装的一个接口,里面封装了一些手势操作方法。新建类实现该接口并将该对象传入GestureDetector构造方法。
class MygestureListener implements GestureDetector.OnGestureListener{
@Override
public boolean onDown(MotionEvent motionEvent) {
return false;
}
@Override
public void onShowPress(MotionEvent motionEvent) {
}
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
return false;
}
@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
return false;
}
@Override
public void onLongPress(MotionEvent motionEvent) {
}
/**
*
* @param motionEvent 第一个action_down手势
* @param motionEvent1 最后一个action_move手势
* @param v x轴上的移动速度 像素/s
* @param v1 y轴上的移动速度 像素/s
* @return
*/
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
return false;
}
}
然后我们给需要设置手势操作的view配置上GestureDetector
比如 view.setOnTouchListener(new onTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
if (g!=null){
return mGestureDetector.onTouchEvent(event);
}
return false;
}
});
就是给view的touch监听返回值设置为手势监听,这样对view的手势操作就会调用GestureListener中的方法。
二、实现跟随手指滑动的activity:
实现原理也是通过对手势的监听,然后根据手指滑动的距离进行activity切换,上面的GestureDetector不行,他不能时时的监听当前的坐标位置。
所以实现方法:实现activity的onTouchEvent方法。然后在里面监听手指移动的位置然后移动activity的decorview。
为什么要移动decorview?首先一个屏幕识图组成部分是由两个方面组成的:xml识图+actionbar,这2个识图都会被添加到decorview中,所以要想实现移动识图的效果就是去移动decorview。
DecorView dv = getWindow().getDecorView();
获取屏幕宽高:
// 获得手机屏幕的宽度和高度,单位像素
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
screenWidth = metrics.widthPixels;
screenHeight = metrics.heightPixels;
然后在onTouchEvent方法中:
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){// 当按下时
// 获得按下时的X坐标
downX = event.getX();
}else if(event.getAction() == MotionEvent.ACTION_MOVE){// 当手指滑动时
// 获得滑过的距离
float moveDistanceX = event.getX() - downX;
if(moveDistanceX > 0){// 如果是向右滑动
decorView.setX(moveDistanceX); // 设置界面的X到滑动到的位置
}
}else if(event.getAction() == MotionEvent.ACTION_UP){// 当抬起手指时
// 获得滑过的距离
float moveDistanceX = event.getX() - downX;
if(moveDistanceX > screenWidth / 2){
// 如果滑动的距离超过了手机屏幕的一半, 结束当前Activity
finish();
}else{ // 如果滑动距离没有超过一半
// 恢复初始状态
decorView.setX(0);
}
}
return super.onTouchEvent(event);
}
但是这样写的效果是识图可以移动,但是前一个activity并没有再后一个activity滑动时显示出来,所以要给activity设置透明背景:
这样activity就可以跟随手指滑动了,但是还有一个问题就是效果比较生硬。所以要给decorview移动设置属性动画:
从大于屏幕1/2的地方到屏幕的宽度:
/**
* 从当前位置一直往右滑动到消失。
* 这里使用了属性动画。
*/
private void continueMove(float moveDistanceX){
// 从当前位置移动到右侧。
ValueAnimator anim = ValueAnimator.ofFloat(moveDistanceX, screenWidth);
anim.setDuration(1000); // 一秒的时间结束, 为了简单这里固定为1秒
anim.start();
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 位移
float x = (float) (animation.getAnimatedValue());
decorView.setX(x);
}
});
// 动画结束时结束当前Activity
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
finish();
}
});
}
从小于屏幕1/2的地方到0:
/**
* Activity被滑动到中途时,滑回去~
*/
private void rebackToLeft(float moveDistanceX){
ObjectAnimator.ofFloat(decorView, "X", moveDistanceX, 0).setDuration(300).start();
}