android事件处理之基于监听

时间:2022-12-15 13:17:46

Android提供了了两种事件处理方式:基于回调和基于监听。

基于监听:

监听涉及事件源,事件,事件监听器。用注册监听器的方法将某个监听器注册到事件源上,就可以对发生在事件源上的时间进行监听。

最简单的的一个例子:单击按钮改变文本框里的文字。

界面布局:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools
="http://schemas.android.com/tools"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:orientation
="vertical"
tools:context
="com.example.zjlyyq.shijianchuli.MainActivity">

<EditText
android:layout_width
="match_parent"
android:layout_height
="wrap_content"
android:text
="还没有任何操作"
android:id
="@+id/et1"/>
<LinearLayout
android:layout_width
="match_parent"
android:layout_height
="wrap_content"
android:orientation
="horizontal">
<Button
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:text
="按钮1"
android:id
="@+id/bt1"/>
<Button
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:text
="按钮2"
android:id
="@+id/bt2"/>
</LinearLayout>
</LinearLayout>

MainActivity:

package com.example.zjlyyq.shijianchuli;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bt1
= (Button)findViewById(R.id.bt1);
Button bt2
= (Button)findViewById(R.id.bt2);
//为按钮绑定监听器
bt1.setOnClickListener(new MyClickListener());
bt2.setOnClickListener(
new MyClickListener());
}
//定义一个单击事件的监听器
class MyClickListener implements View.OnClickListener{
@Override
public void onClick(View v) {
EditText et1
= (EditText)findViewById(R.id.et1);
et1.setText(
"bt1被单击了");
}
}
}

android事件处理之基于监听android事件处理之基于监听

注:以上程序采用内部类的形式。 

事件由系统自动生成事件对象,事件对象会作为参数传给在事件源上注册的事件监听器。在上面的程序中,并没有事件对象,这是因为事件源触发的事件足够简单,无需封装事件对象,也就没有将数据对象传入监听器。但在更复杂的事件中,例如:键盘事件,触屏事件,包含更多的信息,Android会将时间信息封装成XxxEvent对象。并将对象作为参数传给监听器。

下面看个复杂点的例子:控制飞机移动

由于几乎不需要界面布局,该游戏直接使用一个PlaneView作为Activity显示的内容,并未该PlaneView增加触摸监听器即可。

PlaneView:

package com.example.zjlyyq.shijianchuli;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;

/**
* Created by zjlyyq on 2016/12/10.
*/
public class PlaneView extends View {
public float currentX;
public float currentY;
public Bitmap plane;
public PlaneView(Context context) {
super(context);
//定义飞机
plane = BitmapFactory.decodeResource(context.getResources(),R.drawable.plane);
setFocusable(
true);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//创建画笔
Paint p = new Paint();
//绘制飞机
canvas.drawBitmap(plane,currentX,currentY,p);
}
}

MainActivity:

package com.example.zjlyyq.shijianchuli;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {
private int speed = 10;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//去掉窗口标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
//全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
final PlaneView planeView = new PlaneView(this);
setContentView(planeView);

//获取窗口管理器
WindowManager windowManager = getWindowManager();
Display display
= windowManager.getDefaultDisplay();
DisplayMetrics metrics
= new DisplayMetrics();
//获取屏幕宽和高
display.getMetrics(metrics);
//设置飞机初始位置
planeView.currentX = metrics.widthPixels/2;
planeView.currentY
= metrics.heightPixels - 40;
//为planeView组件的键盘事件绑定监听器
planeView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
switch (event.getKeyCode()){
//控制飞机下移
case KeyEvent.KEYCODE_PAGE_DOWN:
planeView.currentY
+= speed;
break;
//控制飞机上移
case KeyEvent.KEYCODE_PAGE_UP:
planeView.currentY
-= speed;
break;
}
//通知palneView组件重绘
planeView.invalidate();
return true;
}
});
//为planeView组件的触屏事件绑定监听器
planeView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
float x,y;
//获得触屏事件的位置
x = event.getX();
y
= event.getY();
planeView.currentY
= y;
planeView.currentX
= x;
//通知palneView组件重绘
planeView.invalidate();
return true;
}
});
}
}

这个程序监听器采用匿名内部类的形式,并传入了MotionEvent对象。