Android之事件机制

一.MotionEvent机制(触屏)

1.触屏操作的理解

最基本的操作类型:

down : 手指按下

move : 手指在屏幕上移动

up : 手指从屏幕上离开

触屏操作的顺序:  

down->move->move->…->up

2.相关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) : 拦截事件的回调方法

3.触摸事件的分发与处理

事件产生的顺序为: down-->move-->move...--->up

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

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

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

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

4.项目练习

1)功能描述:

通过手指移动来拖动图片

控制图片不能超出屏幕显示区域

2)技术点:
MotionEvent处理

对View进行动态定位(layout)

3).用到的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的父视图对象
4).代码实现:

package com.example.event_06;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class MotionEventTestActivity extends Activity implements OnTouchListener {
	private ImageView iv_touch;
	private LinearLayout parentView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_touch);
		
		//得到MyImageView
		iv_touch = (ImageView) findViewById(R.id.iv_touch);
		
		parentView = (LinearLayout) iv_touch.getParent();
		
		//设置touch监听 
		iv_touch.setOnTouchListener(this);
	}

	private int lastX;
	private int lastY;
	private int maxRight;
	private int maxBottom;
	@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:
			//得到父视图的right/bottom
			if(maxBottom==0){//保证只赋一次值
				maxRight = parentView.getRight();
				maxBottom = parentView.getBottom();
			}
			
			//第一次记录lastX/lastY
			lastX = eventX;
			lastY = eventY;
			break;
		case MotionEvent.ACTION_MOVE:
			//计算事件的偏移
			int dx = eventX - lastX;
			int dy = eventY - lastY;
			//根据事件的偏移来移动imageView 
			int left = iv_touch.getLeft() + dx;
			int right = iv_touch.getRight() + dx;
			int bottom = iv_touch.getBottom() + dy;
			int top = iv_touch.getTop() + dy;
			//限制left >=0
			if(left<0){
				right -= left;
				left = 0;
			}
			//限制top
			if(top<0){
				bottom -= top;
				top = 0;
			}
			//限制right <=maxRight
			if(right > maxRight){
				left -= (right-maxRight);
				right = maxRight;
			}
			//限制bottom <= maxBottom
			if(bottom > maxBottom){
				top -= bottom - maxBottom;
				bottom = maxBottom;
			}
			iv_touch.layout(left, top, right, bottom);
			//再次记录lastX/lastY
			lastX = eventX;
			lastY = eventY;
			break;

		default:
			break;
		}
		return true;//所有的motionEvent都交给imageView处理
	}
}

二,KeyEvent机制(按键)

1.相关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) : 长按按键的回调

2.项目练习

功能描述:

第一次按back键, 只Toast提示, 不退出应用

2S内连按两次back键才退出应用

技术点:

KeyEvent处理

延迟消息的处理

代码实现:

package com.example.event_06;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.widget.Toast;

public class KeyEventTestActivity extends Activity {
	private boolean exit = false;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_key_event_test);
	}
	
	
	
	@Override
	public boolean dispatchKeyEvent(KeyEvent event) {
		Log.e("TAG", "dispatchKeyEvent() keycode = " + event.getKeyCode() +"action = "+ event.getAction());
		return super.dispatchKeyEvent(event);
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		Log.e("TAG", "onKeyDown() keycode = " + event.getKeyCode() +"action = "+ event.getAction());
		//startTracking():追踪事件,用于长按监听
		event.startTracking();
		//return super.onKeyDown(keyCode, event);
		return true;
	}
	

	private Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			if(msg.what==1){
				exit = false;
			}
				
		};
	};
	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		if(event.getKeyCode()==KeyEvent.KEYCODE_BACK){
			if(!exit){
				exit = true;
				Toast.makeText(this , "再按一次就退出应用", 0).show();
				//发消息延迟两秒将exit=false
				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、付费专栏及课程。

余额充值