android的事件处理机制
一、基于监听的处理机制
控件 : 是编程中用到的,按钮就算是一个控件,窗口也是等等
组件 : 是软件的一部分.软件的组成部分.
插件 : 网页中用到的,flash插件,没有它浏览器不能播放flash.
1. 监听的处理流程
·基于监听的事件处理主要涉及3个对象:
Event Source(事件源):事件发生的场所,通常就是组件,每个组件在不同情况下发生的事件不尽 相同。
Event (事件):事件封装了界面组件上发生的事件,通常是用户的操作。
EventListener(事件监听器):负责监听事件源所发生的事件,并对各种事件做出相应的处理。
执行步骤:
step1:为事件对象添加监听。
step2:当事件发生时,系统会将事件封装成相应类型的事件对象。
step3:监听器接收到事件对象后调用相应的事件处理来处理事件。
几个常用的事件监听接口:
- View.OnClickListener:单击事件的事件监听器必须要实现的接口
- View.OnCreateContextMenuListener:创建上下文菜单的事件监听器必须要实现的接口
- View.OnFocusChangedListener:焦点改变事件的事件监听器必须实现的接口
- View.OnKeyListener:按钮事件的事件监听器必须实现的接口
- View.OnLongClickListener:长单击事件的事件监听器必须要实现接口
- View.OnTouchListener:触摸事件的事件监听器必须要实现的接口
与普通java方法调用不同的是:普通java程序里的方法是由程序主动调用的,而事件处理中的初见处理器方法是由系统负责调用的
1. 内部类作为事件 监听器类
import android.app.Activity; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.Toast;
public class MainActivity extends Activity { private Button Button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button = (android.widget.Button) findViewById(R.id.button); Button.setOnClickListener(new EnterClickListener()); }
class EnterClickListener implements android.view.View.OnClickListener{ @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "内部类形式", Toast.LENGTH_SHORT).show(); } }
}
2. 外部类作为事件监听器类
public class MainActivity extends Activity { private EditText etNumber1; private EditText etNumber2; private Button btnResult;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findView(); btnResult.setOnClickListener(new Claculator(this,etNumber1,etNumber2)); } private void findView() { etNumber1 = (EditText) findViewById(R.id.operator1); etNumber2 = (EditText) findViewById(R.id.operator2); btnResult = (Button) findViewById(R.id.result); } } 外部实现类: import android.app.Activity; import android.view.View; import android.view.View.OnClickListener; import android.widget.EditText; import android.widget.Toast; public class Claculator implements OnClickListener { private Activity activity; private EditText etNumber1; private EditText etNumber2; public Claculator(Activity activity,EditText editText,EditText editText2){ this.activity = activity; this.etNumber1 = editText; this.etNumber2 = editText2; } @Override public void onClick(View v) { int number1 = Integer.parseInt(etNumber1.getText().toString().trim()); int number2 = Integer.parseInt(etNumber2.getText().toString().trim()); int result = number1 + number2; Toast.makeText(activity, "计算结果为:" + result, Toast.LENGTH_SHORT).show(); }
3. 匿名内部类作为事件监听器类
public class MainActivity extends Activity { private EditText etNumber1; private EditText etNumber2; private Button btnResult; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findView(); //btnResult.setOnClickListener(new Claculator(this,etNumber1,etNumber2));//是用外部类 //是用匿名内部类 btnResult.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int number1 = Integer.parseInt(etNumber1.getText().toString().trim()); int number2 = Integer.parseInt(etNumber2.getText().toString().trim()); int result = number1 + number2; Toast.makeText(getApplicationContext(), "计算结果为:" + result, Toast.LENGTH_SHORT).show(); } }); } private void findView() { etNumber1 = (EditText) findViewById(R.id.operator1); etNumber2 = (EditText) findViewById(R.id.operator2); btnResult = (Button) findViewById(R.id.result); }
4.Activity作为事件监听器
public class MainActivity extends Activity implements OnClickListener{ private EditText etNumber1; private EditText etNumber2; private Button btnResult; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findView(); //btnResult.setOnClickListener(new Claculator(this,etNumber1,etNumber2));//是用外部类 //是用匿名内部类 /*btnResult.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int number1 = Integer.parseInt(etNumber1.getText().toString().trim()); int number2 = Integer.parseInt(etNumber2.getText().toString().trim()); int result = number1 + number2; Toast.makeText(getApplicationContext(), "计算结果为:" + result, Toast.LENGTH_SHORT).show(); } });*/ btnResult.setOnClickListener(this); } private void findView() { etNumber1 = (EditText) findViewById(R.id.operator1); etNumber2 = (EditText) findViewById(R.id.operator2); btnResult = (Button) findViewById(R.id.result); } @Override public void onClick(View v) { int number1 = Integer.parseInt(etNumber1.getText().toString().trim()); int number2 = Integer.parseInt(etNumber2.getText().toString().trim()); int result = number1 + number2; Toast.makeText(getApplicationContext(), "计算结果为:" + result, Toast.LENGTH_SHORT).show(); } }
5. 绑定到组件事件属性
<Button android:paddingTop="20dp" android:id="@+id/result" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="结果" android:onClick="getResult"/>
public void getResult(View view){ int number1 = Integer.parseInt(etNumber1.getText().toString().trim()); int number2 = Integer.parseInt(etNumber2.getText().toString().trim()); int result = number1 + number2; Toast.makeText(getApplicationContext(), "计算结果为:" + result, Toast.LENGTH_SHORT).show(); }
二、基于回调事件
1.回调机制与监听机制
如果说事件监听机制是一种委托的事件处理,那么回调机制则与之相反,对于基于事件的处理模型来说,事件源与事件监听器是统一的,或者说是事件监听器完全消失了,当用户在UI组件上触发某个事件时,组建自己特定的方法将会负责处理事件
为了使回调方法机制类处理UI组件上发生的事件,开发者需要为该组件提供对应的事件处理方法,而java是一种静态语言,无法为某个对象动态的添加方法,因此只能继续是用UI组件类,并通过重写该类的事件处理的方法来实现
- 新建一个工程,布局文件很简单,就一个textview,MainActivity.java中重写了onKeyDown和onKeyUp方法
代码如下
package cn.aiyuan1996.huidiao; import android.app.Activity; import android.os.Bundle; import android.view.Gravity; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private TextView text;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView) findViewById(R.id.text); } public void showText(String string){ text.setText(string); } public void showToast(String string){ Toast toast = Toast.makeText(this, string, Toast.LENGTH_LONG); toast.setGravity(Gravity.TOP, 0, 100); toast.show(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_0: showText("你按下了数字键0"); break; case KeyEvent.KEYCODE_BACK: showText("你按下了返回键"); break; default: break; } return super.onKeyDown(keyCode, event); }
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_0: showToast("你松开了数字键0"); break; case KeyEvent.KEYCODE_BACK: showToast("你松开了返回键"); break; default: break; } text.setText("你没有按下任何键"); return super.onKeyUp(keyCode, event); } }
几乎所有基于回调的事件都有一个boolean类型的返回值,发方法用于标识该处理方法是否能够完全处理该事件
(1),如果处理事件的回调方法返回的值为true,则表明该处理方法已完全处理该事件,且事件不会被传播出去
(2),如果处理事件的回调方法返回的值为false,则表明该处理方法并未完全处理该事件,且事件会被传播出去
对于基于回调的事件传播而言,某组件上所发生的事件不仅能触发该组件上的回调方法,也会触发该组件所在的activity类的回调方法-只要事件传播到该activity类
基于回调触摸事件处理
屏幕事件的处理方法onTouchEvent(),该方法的返回值与键盘响应事件相同,都是当程序完整的处理的该事件,且不希望其他回调方法再次处理该事件时返回true,否则返回false .
1)屏幕被按:下MotionEvent.getAction()==MotionEvent.ACTION_DOWN
2)离开屏幕:MotionEvent.getAction()==MotionEvent.ACTION_UP
3)在屏幕中拖动:MotionEvent.getAction()==MotionEvent.ACTION_MOVE
Handler类简介
Handler类主要有两个作用:在新启动的线程中发送消息,在主线程中获取和处理消息
只能通过回调的方法来实现-开发者只需要重写Handler类中处理的消息的方法即可,当新启动的线程发送消息时,消息会发送到与之关联的MessageQueue,而Handler会不断的从MessageQueue中获取并处理消息-这将导致Handler中的处理消息的方法被回调
下面是Handler类中常用的几个方法
public class MainActivity extends Activity { int[] imgList = new int[]{R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f}; int currentIndex = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ImageView imageView = (ImageView) findViewById(R.id.image); final Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == 0x123){ //动态修改图片 currentIndex++; imageView.setImageResource(imgList[currentIndex%imgList.length]); } } }; if(currentIndex <= imgList.length){ new Timer().schedule(new TimerTask() { @Override public void run() { handler.sendEmptyMessage(0x123); } }, 0,1200); } }