Android事件系统(1)

Android事件系统(1)

我们都知道触摸屏幕可以得到应用响应,例如说我们点击屏幕中的一个按钮,可以弹出一个对话框或者吐司,那么这个触屏事件从产生一直到得到响应是如何在Android系统中传递的呢?接下来我们将用一段时间去阐述Android系统的事件分发处理流程。

MotionEvent

假设现在我们有如下需求需要去实现:

  1. 监听返回键
  2. 监听某一按钮的触摸事件
  3. 实现一个随手指移动的TextView

接下来我们就来逐个实现以上需求,找出Android事件分发的核心。

监听返回键

对于这个需求我们自然而然的想到重写onKeyDown方法,那么让我们看一下完成该需求的代码:

 @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return super.onKeyDown(keyCode, event);
    }

监听某一按钮的触摸事件

        mCustomButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return false;
            }
        });

实现一个随手指移动的TextView

实现的自定义的TextView的代码如下:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.TextView;

/** * Created by TuoZhaoBing on 2016/4/6 0006. */
public class CustomTouchTextView extends TextView{
    public static final String TAG = "CustomTouchTextView";
    private int mStartX,mStartY;
    private Context mContext;

    public CustomTouchTextView(Context context) {
        super(context);
        this.mContext =context;
    }

    public CustomTouchTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext =context;
    }

    public CustomTouchTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext =context;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:{
                mStartX = (int)event.getRawX();
                mStartY = (int)event.getRawY();
                break;
            }
            case MotionEvent.ACTION_MOVE:{
                    int dx = (int) event.getRawX()-mStartX;
                    int dy = (int) event.getRawY()-mStartY;

                    int l = getLeft()+dx;
                    int b = getBottom()+dy;
                    int r = getRight()+dx;
                    int t = getTop()+dy;
                    if(l<0){
                        l = 0;
                        r = l+getWidth();
                    }

                    if(t<0){
                        t = 0;
                        b = t+getHeight();

                    }

                    if(r> MeasureUtils.getScreenWidth(mContext)){
                        r = MeasureUtils.getScreenWidth(mContext);
                        l = r - getWidth();
                    }

                    if(b>MeasureUtils.getScreenHeight(mContext)){
                        b = MeasureUtils.getScreenHeight(mContext);
                        l = b-getHeight();
                    }
                    layout(l, t, r, b);
                    mStartX = (int) event.getRawX();
                    mStartY = (int) event.getRawY();
                    postInvalidate();
                }
                break;
            case MotionEvent.ACTION_UP:{
                break;
            }
        }
        return true;
    }
}

通过上述三个例子我们观察到,在Android系统中针对不同的事件对应着不同的Event,这里KeyEvent对应着键盘触摸事件,MotionEvent对应着一般的Touch事件。在不同的Event中包含着该类事件的重要信息,以MotionEvent为例,一个MotionEvent中包含了触摸点坐标,事件类型,触摸点数量等基本信息,我们正是利用这些信息进行事件处理的。
官网上关于MotionEvent的说明是这样的:
**
Object used to report movement (mouse, pen, finger, trackball) events. Motion events may hold either absolute or relative movements and other data, depending on the type of device.
Motion events describe movements in terms of an action code and a set of axis values. The action code specifies the state change that occurred such as a pointer going down or up. The axis values describe the position and other movement properties
**
这句话的意思是这个对象用于持有瞬时事件的数据,这些数据依赖于设备类型,在MotionEvent中描述了事件的Action和坐标,MotionEvent对象通常作为一个常量传递给View。
接下来我们队MotionEvent所持有数据进行解释:
1.触摸事件信息

    event.getAction() //获取触控动作比如ACTION_DOWN
    event.getPointerCount(); //获取触控点的数量,比如2则可能是两个手指同时按压屏幕
    event.getPointerId(nID); //对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取索引
    event.getX(nID); //获取第nID个触控点的x位置
    event.getY(nID); //获取第nID个点触控的y位置
    event.getPressure(nID); //LCD可以感应出用户的手指压力,当然具体的级别由驱动和物理硬件决定的
    event.getDownTime() //按下开始时间
    event.getEventTime() // 事件结束时间
    event.getEventTime()-event.getDownTime()); //总共按下时花费时间

2.事件类型
主要的事件类型有:
ACTION_DOWN: 表示用户开始触摸.
ACTION_MOVE: 表示用户在移动(手指或者其他)
ACTION_UP:表示用户抬起了手指
ACTION_CANCEL:表示手势被取消了,一些关于这个事件类型的讨论见:stackoverflow
ACTION_OUTSIDE: 表示用户触碰超出了正常的UI边界.但是对于多点触控的支持,Android加入了以下一些事件类型.来处理,如另外有手指按下了,有的手指抬起来了.等等:
ACTION_POINTER_DOWN:有一个非主要的手指按下了.
ACTION_POINTER_UP:一个非主要的手指抬起来了
3.事件发生位置(坐标)
getX() 获得事件发生时,触摸的中间区域在屏幕的X轴.
getY() 获得事件发生时,触摸的中间区域在屏幕的X轴.
getX(int pointerIndex) ,在多点触控中获得对应手指事件的发生位置. 获得Y轴用getY(int pointerIndex)

你可能感兴趣的:(android,MotionEven)