Android处理touch事件

Android事件处理机制是基于Listener实现的,比如触摸屏相关的事件,就是通过onTouchListener实现;
所有View的子类都可以通过setOnTouchListener()、setOnKeyListener()等方法来添加对某一类事件的Listener;
Listener一般以Interface的方式来提供,其中包含一个或多个abstract方法,我们需要实现这些方法来完成onTouch()、onKey()等操作。这样,程序便可以在特定的事件被dispatch到该view的时候,通过callback函数给予适当的响应。

当用户触摸屏幕的时候,会产生许多手势,可以通过下列方式接收事件处理:

1.View类有个View.onTouchListener内部接口,可以通过重写它的onTouch(View v, MotionEvent event)方法,处理一些在该控件中触发的touch事件;
2.也可以通过重写Activity的onTouchEvent方法;
3.通过Android sdk提供的GestureDetector类

onTouch()方法:

当一个View绑定了OnTouchListener后,当有Touch事件触发时,就会调用onTouch方法。当把手放到View上后,onTouch方法被一遍一遍的调用

用法示例1: 在activity中使用

package xxxx;

import android.os.Bundle;
import android.app.Activity;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;

public class MainActivity extends Activity {
    //声明ImageView对象
    private ImageView testImg = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //ImageView对象
        testImg=(ImageView)super.findViewById(R.id.img);
        //注册OnTouch监听器
        testImg.setOnTouchListener(new ImgOnTouchListener());
    }
    //OnTouch监听器
    private class ImgOnTouchListener implements OnTouchListener{
        @Override
        public boolean onTouch(View v, MotionEvent event){
            /*
                do things
            */
            return true;
        }
    }
}

用法示例2:控件继承

package xxxx;
 
import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.util.AttributeSet;

public class TestImg extends ImageView implements OnTouchListener {

    // 构造函数
    public TestImg(Context context) {
        super(context);
    }

    public TestImg(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    // 重写onTouch
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        /* do things */
        return true;
    }
}

onTouchEvent()方法:

重写了Activity的onTouchEvent方法后,当屏幕有Touch事件时,此方法就会被调用。当把手放到Activity上时,onTouchEvent方法会一遍一遍的被调用

用法示例

@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		switch (event.getAction())
		{
			case MotionEvent.ACTION_DOWN:
				// do things
			break;
			case MotionEvent.ACTION_MOVE:
				// do things
			break;
			case MotionEvent.ACTION_UP:
				// do things
			break;
		}
		return true;

GestureDetector:


在onTouch()/onTouchEvent()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector * 来分析是否有合适的callback函数来处理用户的手势

GestureDetector这个类对外提供了两个接口和一个外部类
接口:OnGestureListener,OnDoubleTapListener,OnContextClickListener(不常用)
内部类:SimpleOnGestureListener

用法示例1:GestureDetector.OnGestureListener

package xxxx;

import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.view.GestureDetector;


public class TestImg extends ImageView {

    private GestureDetector mGestureListener;

    // 构造函数
    public TestImg(Context context) {
        super(context);
    }

    public TestImg(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureListener = new GestureDetector(context, new GestureListener());
    }

    // onTouchEvent
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /* do things */

        return mGestureListener.onTouchEvent(event); // 或者使用onTouch
    }

    private class GestureListener implements GestureDetector.OnGestureListener {
        @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) {
            return false;
        }
    }
}

用法示例2:GestureDetector.OnDoubleTapListener

package xxxx;

import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.view.GestureDetector;


public class TestImg extends ImageView {

    private GestureDetector mGestureListener;

    // 构造函数
    public TestImg(Context context) {
        super(context);
    }

    public TestImg(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureListener = new GestureDetector(context, new GestureListener());
        mGestureListener.setOnDoubleTapListener(new DoubleTapListener());
    }

    // onTouchEvent
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /* do things */

        return mGestureListener.onTouchEvent(event); // 或者使用onTouch
    }

    private class GestureListener implements GestureDetector.OnGestureListener {
        @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) {
            return false;
        }
    }

    private class DoubleTapListener implements GestureDetector.OnDoubleTapListener {
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return false;
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            return false;
        }

        @Override
        public boolean onDoubleTapEvent(MotionEvent e) {
            return false;
        }
    }
}

用法示例3:GestureDetector. SimpleOnGestureListener

import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import android.view.GestureDetector;


public class TestImg extends ImageView {

    private GestureDetector mGestureListener;

    // 构造函数
    public TestImg(Context context) {
        super(context);
    }

    public TestImg(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureListener = new GestureDetector(context, new SimpleGestureListener());
    }

    // onTouchEvent
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /* do things */

        return mGestureListener.onTouchEvent(event); // 或者使用onTouch
    }

    public class SimpleGestureListener extends GestureDetector.SimpleOnGestureListener {

        /*OnGestureListener*/

        // onDown:用户按下屏幕就会触发,在其他的事件前面
        @Override
        public boolean onDown(MotionEvent e) {
            return false;
        }

        // onShowPress:用户收到onDown事件,100ms后,还没有拖动或者松开,那么onShowPress就会执行。具体时间可以参照GestureDetector源码
        @Override
        public void onShowPress(MotionEvent e) {
        }

        // onSingleTapUp:用户手指松开(UP事件)的时候如果没有执行onScroll()和onLongPress()这两个回调的话,就会回调这个,说明这是一个点击抬起事件,但是不能区分是否双击事件的抬起。
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }

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

        // onLongPress:长按触摸屏,超过一定时长,就会触发这个事件。源码里是收到onDown,500ms后
        @Override
        public void onLongPress(MotionEvent e) {
        }

        // onFling:滑屏,用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }

        /*OnDoubleTapListener*/

        // onSingleTapConfirmed:单击事件。用来判定该次点击是SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,如果只点击一次,系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,
        // 然后触发SingleTapConfirmed事件。触发顺序是:OnDown->OnsingleTapUp->OnsingleTapConfirmed
        // onSingleTapUp和onSingleTapConfirmed的区别是:onSingleTapUp,只要手抬起就会执行,而onSingleTapConfirmed,如果双击的话,则onSingleTapConfirmed不会执行。
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return false;
        }

        // onDoubleTap:双击事件
        // 在第二下点击时,先触发OnDoubleTap,然后再触发OnDown(第二次点击)
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            return false;
        }

        // onDoubleTapEvent:双击间隔中发生的动作。指触发onDoubleTap以后,在双击之间发生的其它动作,包含down、up和move事件
        // 在触发OnDoubleTap以后,就开始触发onDoubleTapEvent了,onDoubleTapEvent后面的数字代表了当前的事件,0指ACTION_DOWN,1指ACTION_UP,2 指ACTION_MOVE
        @Override
        public boolean onDoubleTapEvent(MotionEvent e) {
            return false;
        }

        /*OnContextClickListener*/
        @Override
        public boolean onContextClick(MotionEvent e) {
            return false;
        }
    }
}

Touch事件的传递:


在一个Activity里面放一个控件的实例c,并且这个c的属性设定为march_parent

当把手放到屏幕上时,首先控件c响应Touch事件,执行onTouch方法。
如果onTouch返回值为true,表示这个Touch事件被onTouch方法处理完毕,不会把Touch事件再传递给Activity
也就是说onTouchEvent方法不会被调用,当把手放到屏幕上后,onTouch方法会被一遍一遍的调用
 
如果onTouch返回值为false,表示这个Touch事件没有被c完全处理,onTouch返回以后,Touch事件被传递给Activity,
onTouchEvent方法调用,当把手放到屏幕上后,onTouch方法调用一次后,onTouchEvent方法被一遍一遍的调用

参考:
https://blog.csdn.net/lc_miao/article/details/78274840
https://blog.csdn.net/carson_ho/article/details/54136311
https://blog.csdn.net/harvic880925/article/details/39520901

posted on 2020-04-27 20:28  JJ_S  阅读(531)  评论(0编辑  收藏  举报