基于监听的事件处理
Android系统中引用了三个事件模型:
- 事件 ———改变事件源的状态的对象: 点击,触摸.键盘按键事件
- 事件源————触发事件的对象:按钮,组件
- 事件监听器———— 处理事件
Android中的事件监听器
事件监听器 |
事件 |
功能描述 |
OnClickListener |
单击事件 |
当用户点击某个组件或者方向键触发该事件 |
OnFoucusChangeListener |
焦点事件 |
当组件获得或者失去焦点时触发该事件 |
OnKeyListener |
按键事件 |
当用户按下或者释放设备上的某个按键触发的事件 |
OnTouchListener |
触摸事件 |
当触碰屏幕时触发该事件 |
OnCreateContextMenuListener |
创建上下文菜单事件 |
当创建上下文菜单时触发该事件 |
OnCheckedChangeListener |
选项改变事件 |
当选择改变时触发该事件 |
在程序中实现事件监听器,通常有以下五种形式:
- 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 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);
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); } }
|