-
1. 提出问题?
1). Android是如何响应对其中的某个视图的触控操作呢? --->MotionEvent
Android是如何响应对手机的按键的操作呢? ---->KeyEvent
屏幕触控(MotionEvent)机制
1). 事件类型:
down 手指按下
move 手指在屏幕上移动
up 手指从屏幕上离开
事件发生的顺序:
down--->move-->move-->move-->....-->up
对屏幕的任何一个操作,系统都会创建一个MotionEvent对象来对应这个操作
疑问:点击和长按又是什么呢?
操作事件:
分发--->dispatchTouchEvent()
处理--->onTouchEvent() onTouch()
消费--->处理事件的方法返回true 当前事件对象就结束了
-
3. 按键(KeyEvent)机制
1). 事件类型
down
up
2). API:
<?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=".moveImage">
<ImageView
android:id="@+id/iv_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/diglett"
/>
</RelativeLayout>
package com.example.testapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class moveImage extends AppCompatActivity implements View.OnTouchListener {
private ImageView iv_main;
private RelativeLayout parentView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_move_image);
iv_main = (ImageView) findViewById(R.id.iv_main);
parentView = (RelativeLayout) iv_main.getParent();
// 设置touch监听
iv_main.setOnTouchListener(this);
}
private int lastX;
private int lastY;
private int maxRigth;
private int maxBottom;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// 得到事件的坐标
int eventX = (int) motionEvent.getRawX();
int eventY = (int) motionEvent.getRawY();
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
// 得到父视图的 right/bottom
if(maxRigth==0){
maxRigth = 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_main.getLeft()+dx;
int top = iv_main.getTop()+dy;
int right = iv_main.getRight()+dx;
int bottom = iv_main.getBottom()+dy;
//限制left >=0
if(left<0) {
right += -left;
left = 0;
}
//限制top
if(top<0) {
bottom += -top;
top = 0;
}
//限制right <=maxRight
if(right>maxRigth) {
left -= right-maxRigth;
right = maxRigth;
}
//限制bottom <=maxBottom
if(bottom>maxBottom) {
top -= bottom-maxBottom;
bottom = maxBottom;
}
iv_main.layout(left,top,right,bottom);
// 再次记录lastX和lastY
lastX = eventX;
lastY = eventY;
break;
default:
break;
}
return true; //所有的motionEvent都交给imageView处理
}
}
_连续2次Back退出应用
package com.example.testapplication;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.widget.Toast;
public class eventBack extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_back);
}
private boolean exit = false; // 标识是否可以退出
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(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, "再按一次就退出应用", Toast.LENGTH_SHORT).show();
// 发消息延迟2s将exit= false
handler.sendEmptyMessageDelayed(1,2000);
return true;
}
}
return super.onKeyUp(keyCode, event);
}
}