基于监听的事件处理

Android系统中引用了三个事件模型:

  • 事件 ———改变事件源的状态的对象: 点击,触摸.键盘按键事件
  • 事件源————触发事件的对象:按钮,组件
  • 事件监听器———— 处理事件

Android中的事件监听器

事件监听器 事件 功能描述
OnClickListener 单击事件 当用户点击某个组件或者方向键触发该事件
OnFoucusChangeListener 焦点事件 当组件获得或者失去焦点时触发该事件
OnKeyListener 按键事件 当用户按下或者释放设备上的某个按键触发的事件
OnTouchListener 触摸事件 当触碰屏幕时触发该事件
OnCreateContextMenuListener 创建上下文菜单事件 当创建上下文菜单时触发该事件
OnCheckedChangeListener 选项改变事件 当选择改变时触发该事件

在程序中实现事件监听器,通常有以下五种形式:

  • Activity本身作为事件监听器:通过Activity实现监听器接口,并实现事件处理方法
  • 匿名内部类形式:使用匿名内部类创建事件监听器对象
  • 内部类形式:将事件监听类定义为当前类的内部类
  • 外部类形式:将事件监听类定义为普通外部类
  • 绑定标签:在布局文件中为指定标签绑定事件处理方法

实现基于监听的事件处理步骤:

  1. 实现事件监听器类,在事件处理方法中编写事件处理代码
  2. 获取事件源(组件)
  3. 在相应的组件上注册监听器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.gallifrey.testapplication2;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class TestActivity02 extends AppCompatActivity implements View.OnClickListener {
private Button btnOne;
private Button btnTwo;
private Button btnThree;
private Button btnFour;
private Button btnFive;
private TextView tvOne;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test02);
btnOne=findViewById(R.id.btn_one);
btnTwo=findViewById(R.id.btn_two);
btnThree=findViewById(R.id.btn_three);
btnFour=findViewById(R.id.btn_four);
btnFive=findViewById(R.id.btn_five);
tvOne=findViewById(R.id.tv_one);


//Activity继承OnClickListener接口,本身作为监听器
btnOne.setOnClickListener(TestActivity02.this);
//匿名内部类监听器
btnTwo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
tvOne.setText("匿名内部类作为监听器");
}
});

//内部类实现监听器
btnThree.setOnClickListener(new InnerListener());
//外部类监听器
btnFour.setOnClickListener(new OuterListener(tvOne));

}

@Override
public void onClick(View view) {
tvOne.setText("Activity本身作为监听器");
}

//绑定标签
public void showText(View view) {
tvOne.setText("绑定标签形式");
}


class InnerListener implements View.OnClickListener{

@Override
public void onClick(View view) {
tvOne.setText("普通内部类作为监听器");
}
}
}
  • 监听外部类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.gallifrey.todayapplication;

import android.view.View;
import android.widget.Toast;

public class MyOuterClickListener implements View.OnClickListener {
private MainActivity mainActivity;
public MyOuterClickListener(MainActivity activity){
mainActivity=activity;
}
@Override
public void onClick(View view) {
Toast.makeText(mainActivity,"Outer Click", Toast.LENGTH_LONG).show();
}
}
  • 绑定标签
1
2
3
4
5
6
7
<Button
android:id="@+id/btn_event"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="showToast"
android:text="Event Click"
android:textSize="30sp" />

基于回调机制的事件处理

在回调机制的事件处理中,事件源和事件监听器是同一个对象,是统一的

Android为View中提供了事件处理的回调方法:

  • onKeyDown() 用于捕捉手机键盘被按下的事件
  • onKeyUp() 用于捕捉手机键盘被抬起的事件
  • onTouchEvent() 用于处理手机屏幕的触摸事件
  • onFocusChanged() 焦点改变的回调方法

OnKeyDown()方法

  • 用来捕捉手机键盘被按下的事件
1
public boolean onKeyDown (int keyCode, KeyEvent event)
  • 参数keyCode表示被按下的键值
  • 参数event用于封装按键事件的对象
常量名 功能描述
KEYCODE_POWER 电源键
KEYCODE_NOTIFICATION 通知键
KEYCODE_MUTE 话筒静音键
KEYCODE_VOLUME_MUTE 扬声器静音键
KEYCODE_VOLUME_UP 音量增加键
KEYCODE_VOLUME_DOWN 音量减小键
KEYCODE_CALL 拨号键
KEYCODE_ENDCALL 挂机键

onKeyUp()方法

  • 用来捕捉手机键盘按键抬起的事件
1
public boolean onKeyUp (int keyCode, KeyEvent event)
  • 参数keyCode表示触发事件的按键码
  • 参数event是一个事件封装类的对象
  • 返回值为boolean类型

onTouchEvent()方法

  • 用来处理手机屏幕的触摸事件
1
public boolean onTouchEvent (MotionEvent event)
  • 参数event是手机屏幕触摸事件封装类的对象,用于封装件的相关信息
  • 返回值为boolean类型

onFocusChanged()方法

  • 焦点改变的回调方法
1
2
protected void onFocusChanged (
Boolean gainFocus, int direction, Rect previouslyFocusedRect)
  • 每按下一次按键,会调用两次onFocusChanged()方法,一次是某个按钮失去焦点时调用,第二次是另一个按钮获得焦点时调用

  • 常见的焦点相关方法

    | 方法 | 功能描述 |
    | ——————————— | ————————————————————————————— |
    | setFocusable() | 用于设置View是否可以拥有焦点 |
    | isFocusable() | 用于判断View是否可以拥有焦点 |
    | setNextFocusDownId() | 用于设置View的焦点向下移动后获得焦点View的ID |
    | hasFocus() | 用于判断View的父控件是否获得了焦点 |
    | requestFocus() | 用于尝试让此View获得焦点 |
    | isFocusableTouchMode() | 用于设置View是否可以在触摸模式下获得焦点,默认情况下不可用 |

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.gallifrey.todayapplication;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;


import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;

public class MyButton extends AppCompatButton{

public MyButton(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.i("MyButton", "onTouchEvent: ");
break;
}
return true;
}
}
  • ps:返回值为boolean值,为true则表示处理完,为false则activity会继续调用回调方法。优先级:监听器—>组件的回调方法—->组件所在的activity的回调方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.gallifrey.todayapplication;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.EditText;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class MyEditText extends androidx.appcompat.widget.AppCompatEditText {
public MyEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
super.onKeyDown(keyCode, event);
switch (event.getAction()){
case KeyEvent.ACTION_DOWN:
Log.i("MyEditText", "onKeyDown: ");
break;
}
return false;
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
super.onKeyUp(keyCode, event);
switch (event.getAction()){
case KeyEvent.ACTION_UP:
Log.i("MyEditText", "onKeyUp: ");
break;
}
return false;
}

@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {

Log.i("MyEditText", "onFocusChanged: ");

super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
}