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会将时间信息封装成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对象。