事件机制分发

相关API

1. MotionEvent : 触屏事件

int ACTION_DOWN=0 : 代表down

int ACTION_MOVE=2 ; 代表move

int ACTION_UP=1 : 代表up

getAction() : 得到事件类型值

getX() : 得到事件发生的x轴坐标(相对于当前视图)

getRawX() :得到事件发生的x轴坐标(相对于屏幕左顶点)

getY() : 得到事件发生的y轴坐标(相对于当前视图)

getRawY() :得到事件发生的y轴坐标(相对于屏幕左顶点)

2. Activity

boolean dispatchTouchEvent(MotionEvent event) : 分发事件

boolean onTouchEvent(MotionEvent event) : 处理事件的回调

3. View

boolean dispatchTouchEvent(MotionEvent event) : 分发事件

boolean onTouchEvent(MotionEvent event) : 处理事件的回调方法

void setOnTouchListener(OnTouchListener l) : 设置事件监听器

void setOnClickListener(OnClickListener l) : 设置点击监听

void setOnLongClickListener(OnLongClickListener l) : 设置长按监听

void setOnCreateContextMenuListener
(OnCreateContextMenuListener l) : 用于创建菜单

4. ViewGroup

boolean dispatchTouchEvent(MotionEvent ev) : 分发事件

boolean onInterceptTouchEvent(MotionEvent ev) : 拦截事件的回调方法

触摸事件的分发与处理

事件产生的顺序为: down–>move–>move…—>up

事件对象被系统创建后, 首先会调用对应Activity对象的dispatchTouchEvent()进行分发

down在分发给视图对象的过程中要确定消费者(onTouchEvent()返回true),如果都返回false, 那事件的消费者只能是Activity了

后面的move和up事件, 将事件分发给消费者(可能是视图对象,也可能是Activity)处理, 如果视图不消费, 直接交给Activity处理消费

每个事件都需要有一个消费者

案例图片移动

用到的View相关方法

int getLeft()

得到当前视图左顶点相对父视图的X轴坐标

int getTop()

得到当前视图左顶点相对父视图的Y轴坐标

int getRight()

得到当前视图右下角点相对父视图的X轴坐标

int getBottom()

得到当前视图右下角点相对父视图的Y轴坐标

layout(int left, int top, int right, int bottom) :

动态指定当前视图在父视图中的定位, 参数为相对父视图的坐标

ViewParent getParent() :

得到当前View的父视图对象

布局很简单

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

<ImageView
    android:id="@+id/image"
    android:layout_width="120dp"
    android:layout_height="120dp"
    android:src="@drawable/logo"
    android:layout_alignParentTop="true"
    android:layout_alignParentStart="true" />

</RelativeLayout>

移动imageview并设置拖动范围

private ImageView iv_main;
private RelativeLayout parentView;
private int maxRight;
private int maxBottom;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    iv_main = (ImageView) findViewById(R.id.image);
    //获取父布局
    parentView = (RelativeLayout) iv_main.getParent();

    iv_main.setOnTouchListener(this);
}

private int lastX;
private int lastY;

@Override
public boolean onTouch(View v, MotionEvent event) {
    //得到事件的坐标
    int eventX = (int) event.getRawX();
    int eventY = (int) event.getRawY();
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            //第一次记录lastX,lastY
            lastX = eventX;
            lastY = eventY;
            break;
        case MotionEvent.ACTION_MOVE:
            if (maxRight == 0) {
                maxRight = parentView.getRight();
                maxBottom = parentView.getBottom();
            }
            //计算事件的偏移
            int dx = eventX - lastX;
            int dy = eventY - lastY;
            //根据事件偏移量来移动ImageView
            int left = iv_main.getLeft() + dx;
            int right = iv_main.getRight() + dx;
            int top = iv_main.getTop() + dy;
            int bottom = iv_main.getBottom() + dy;
            //限制left
            if (left < 0) {
                right += -left;
                left = 0;
            }
            //限制top
            if (top < 0) {
                bottom += -top;
                top = 0;
            }
            //限制right
            if (right > maxRight) {
                left -= right - maxRight;
                right = maxRight;
            }
            //限制bottom
            if (bottom > maxBottom) {
                top -= bottom - maxBottom;
                bottom = maxBottom;
            }
            iv_main.layout(left, top, right, bottom);
            lastY = eventY;
            lastX = eventX;
            break;
    }
    return true;//事件被消费,由子view处理
}
}

按键的操作

理解

操作的基本类型

down : 手指按下;
up : 手指从按键上离开

按键操作的顺序: downdowndown…—>up

对按键的任何一个操作, 系统都会创建一个KeyEvent对象来对应这个操作

按键的长按监听: down之后一定时间还没有up时会触发长按监听回调

相关API

KeyEvent

int ACTION_DOWN = 0 : 标识down的常量

int ACTION_UP = 1 : 标识up的常量

int getAction() : 得到事件类型

int getKeyCode() : 得到按键的keycode(唯一标识)

startTracking() : 追踪事件, 用于长按监听

Activity

boolean dispatchKeyEvent(KeyEvent event) : 分发事件

boolean onKeyDown(int keyCode, KeyEvent event) : 按下按键的回调

boolean onKeyUp(int keyCode, KeyEvent event) : 松开按键的回调

boolean onKeyLongPress(int keyCode, KeyEvent event) : 长按按键的回调

案例:点击返回键两秒后退出程序

//是否离开
private boolean isExit = false;
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if (msg.what == 1) {
          isExit=false;
        }
        super.handleMessage(msg);
    }
};

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (!isExit) {//不离开
        isExit = true;
        Toast.makeText(this, "再点击一次退出程序", Toast.LENGTH_SHORT).show();
        handler.sendEmptyMessageDelayed(1, 2000);//两秒后执行
        return true;
    }
    return super.onKeyUp(keyCode, event);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值