简单的Android多点触控和手势识别

参考:

https://www.cnblogs.com/devinzhang/archive/2012/02/27/2369942.html

https://www.jianshu.com/p/cafedd319512

https://blog.csdn.net/zhangyalong_android/article/details/69525455

Android 触控事件的核心为onTouchEvent方法,其中用一个32位int来存储动作信息和索引信息,通过简单的与运算和移位运算可以提取出这两个信息,需要用到MotionEvent类的四个常量:

ACTION_MASK = 8(0x00ff)  :动作信息掩码,用于截取目标动作信息;
ACTION_MASK_SHIFT = 8(0x00ff) : 截取动作信息时所需移位个数
ACTION_POINTER_INDEX_MASK =65280(0xff00) :高8位的位置信息掩码,用于截取索引信息(索引指的是第几个手指头)
ACTION_POINTER_INDEX_SHIFT= 8(0x00ff) :截取触控索引时所需的移位个数
其中多点触控中常用的几个方法有:
MotionEvent.getAction() //获取触控动作比如ACTION_DOWN
MotionEvent.getPointerCount(); //获取触控点的数量,比如2则可能是两个手指同时按压屏幕
MotionEvent.getPointerId(nID); //对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取索引
MotionEvent.getX(nID); //获取第nID个触控点的x位置
MotionEvent.getY(nID); //获取第nID个点触控的y位置
MotionEvent.getPressure(nID); //LCD可以感应出用户的手指压力,当然具体的级别由驱动和物理硬件决定的
MotionEvent.getDownTime() //按下开始时间
MotionEvent.getEventTime() // 事件结束时间
MotionEvent.getEventTime()-event.getDownTime()); //总共按下时花费时间

几种动作类型:

ACTION_DOWN  :   第一个手指按下
ACTION_UP    : 最后一个手指离开
ACTION_POINTER_DOWN :非第一个手指按下
ACTION_POINTER_UP : 非最后一个手指离开
ACTION_POINTER_1_DOWN : 这是之前SDK版本所使用的,表示第一个手指按下,它的数值跟ACTION_DOWN是相等的
ACTION_POINTER_2_DOWN:第二根手指按下
ACTION_POINTER_3_DOWN:第三根手指按下
ACTION_POINTER_x_DOWN:第x根手指离开

自己写的Demo:

import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import com.bumptech.glide.Glide;

@RequiresApi(api = 3)
public class MainActivity extends AppCompatActivity {
    private String TAG = getClass().getSimpleName();
    private ImageView imageView;
    private GestureDetector gestureDetector;
    private int num = 1;
    private int downX;
    private int downY;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView)findViewById(R.id.imageview);
        Glide.with(this)
                .load("file:///android_asset/images/1.jpg")
                .into(imageView);

        gestureDetector = new GestureDetector(this,gestureListener);
        imageView.setOnClickListener(clickListener);
        imageView.setOnTouchListener(touchListener);


    }

    private View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            num++;
            String path = "file:///android_asset/images/"+num%4+".jpg";
            Glide.with(MainActivity.this).load(path).into(imageView);
            logd("click 事件发生");

        }
    };

    private View.OnTouchListener touchListener = new View.OnTouchListener() {
        /**
         * Android中触控事件的核心是onTouch事件,用一个32位int来存储动作信息和索引信息,可以使用下面四个常量来提取所需要的信息
         *  ACTION_MASK = 8(0x00ff)  :动作信息掩码,用于截取目标动作信息;
         *  ACTION_MASK_SHIFT = 8(0x00ff) : 截取动作信息时所需移位个数
         *  ACTION_POINTER_INDEX_MASK =65280(0xff00) :高8位的位置信息掩码,用于截取索引信息(索引指的是第几个手指头)
         *  ACTION_POINTER_INDEX_SHIFT= 8(0x00ff) :截取触控索引时所需的移位个数
         *  动作类型:
         *  ACTION_DOWN:第一个手指头按下
         *  ACTION_UP  :最后一个手指离开
         *  ACTION_POINTER_DOWN :非第一个手指按下
         *  ACTION_POINTER_UP :非最后一个手指离开
         *  ACTION_MOVE:手指移动
         *  ACTION_POINTER_1_DOWN : 这是之前SDK版本所使用的,表示第一个手指按下,它的数值跟ACTION_DOWN是相等的
         *  ACTION_POINTER_2_DOWN:第二根手指按下
         *  ACTION_POINTER_3_DOWN:第三根手指按下
         *  ACTION_POINTER_x_DOWN:第x根手指离开
         */
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
//            int action = (motionEvent.getAction() & MotionEvent.ACTION_MASK);
            int action = motionEvent.getActionMasked();
            int index = motionEvent.getActionIndex();
            //这里如果不用GestureDetector的话就得自己根据action的变化来监测手势的变化,这会非常麻烦
            //好在Google提供了GestureDetector,由它来监听手势的变化

//            int index = (motionEvent.getAction()&MotionEvent.ACTION_POINTER_INDEX_MASK)>>motionEvent.ACTION_POINTER_INDEX_SHIFT;
                gestureDetector.onTouchEvent(motionEvent);
                switch (action){
                    //第一个点被按下
                    case MotionEvent.ACTION_DOWN:
                        downX = (int)motionEvent.getX();
                        downY = (int)motionEvent.getY();
                        logd("Action down事件发生");
                        break;
                    //手指移动
                    case MotionEvent.ACTION_MOVE:
                        int moveX = (int)motionEvent.getX();
                        int moveY = (int)motionEvent.getY();
                        if(Math.abs(moveX-downX)>20&&Math.abs(moveY-downY)>20){
                            return true;
                        }
                        logd("Action move 事件发生");
                        break;
                    //最后一个手指离开
                    case MotionEvent.ACTION_UP:
                        logd("Action up事件发生");
                        break;
                    //非第一个点按下
                    case MotionEvent.ACTION_POINTER_DOWN:
                        logd("Action pointer down 事件发生");
                        break;
                    //非最后一个点离开
                    case MotionEvent.ACTION_POINTER_UP:
                        logd("Action pointer up 事件发生");
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        logd("Action cancle 事件发生");
                    default:
                        break;
                }
            //如果return true表示事件已经被消费,onClick事件不会有响应
            return false;
        }
    };

    private void logd(String s) {
        Log.d(TAG,s);
//        Toast.makeText(this,s,Toast.LENGTH_LONG).show();
    }

    private GestureDetector.OnGestureListener gestureListener = new GestureDetector.OnGestureListener() {
        @Override
        public boolean onDown(MotionEvent motionEvent) {
            logd("onDown手势");
            return false;
        }

        @Override
        public void onShowPress(MotionEvent motionEvent) {
            logd("onShowPress手势");
        }

        @Override
        public boolean onSingleTapUp(MotionEvent motionEvent) {
            logd("onSingleTapUp手势");
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
            logd("onScroll手势");
            return false;
        }

        @Override
        public void onLongPress(MotionEvent motionEvent) {
            logd("onLongPress手势");
        }

        @Override
        public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
            logd("onFling手势");
            return false;
        }
    };
}

layout文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="200dp"
        android:layout_height="200dp"/>

</RelativeLayout>

手势识别类:GestureDetector,只需要调用GestureDetector.onTouchEvent(motionEvent),在传入一个GestureDetector.OnGestureListener,就能够识别几种常用手势。

几种手势动作:

OnDown(MotionEvent e):用户按下屏幕就会触发;
onShowPress(MotionEvent e):如果是按下的时间超过瞬间,而且在按下的时候没有松开或者是拖动的,那么onShowPress就会执行
onLongPress(MotionEvent e):长按触摸屏,超过一定时长,就会触发这个事件

onSingleTapUp(MotionEvent e):从名字也可以看出,一次单独的轻击抬起操作,也就是轻击一下屏幕,立刻抬起来,才会有这个触发,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以也就不会触发这个事件

onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) :滑屏,用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发   

onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY):在屏幕上拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法       在ACTION_MOVE动作发生时就会触发

猜你喜欢

转载自blog.csdn.net/shuaizhigen/article/details/82184595