官术网_书友最值得收藏!

4.9 界面事件響應(yīng)

事件是Android平臺(tái)與用戶交互的手段。當(dāng)用戶對(duì)手機(jī)進(jìn)行操作時(shí),會(huì)產(chǎn)生各種各樣的輸入事件,Android框架捕獲到這些事件,進(jìn)而進(jìn)行處理。Android平臺(tái)提供了多種用于獲取用戶輸入事件的方式,考慮到用戶事件都是在特定的用戶界面中產(chǎn)生,因此Android選用使用特定View組件來獲取用戶輸入事件的方式,由View組件提供事件處理的方法。這就是為什么View類內(nèi)部帶有處理特定事件的監(jiān)聽器。

4.9.1 事件監(jiān)聽器

監(jiān)聽器用于對(duì)特定事件進(jìn)行監(jiān)聽,一旦監(jiān)聽到特定事件,則由監(jiān)聽器截獲該事件,并回調(diào)自身的特定方法對(duì)事件進(jìn)行處理。在本章之前的實(shí)例中,我們使用的事件處理方式都是監(jiān)聽器。根據(jù)用戶輸入方式的不同,View組件將截獲的事件分為6種,對(duì)應(yīng)以下6種事件監(jiān)聽器接口:

(1)OnClickListener接口:此接口處理的是單擊事件,例如,在View上進(jìn)行單擊動(dòng)作、在View獲得焦點(diǎn)的情況下單擊“確定”按鈕或者單擊軌跡球都會(huì)觸發(fā)該事件。當(dāng)單擊事件發(fā)生時(shí),OnClickListener接口會(huì)回調(diào)public void onClick(View v)方法對(duì)事件進(jìn)行處理。其中參數(shù)v指的是發(fā)生單擊事件的View組件。

(2)OnLongClickListener接口:此接口處理的是長按事件,當(dāng)長時(shí)間按住某個(gè)View組件時(shí)觸發(fā)該事件。其對(duì)應(yīng)的回調(diào)方法為public boolean onLongClick(View v),當(dāng)返回值true時(shí),表示已經(jīng)處理完此事件,若事件未處理完,則返回false,該事件還可以繼續(xù)被其他監(jiān)聽器捕獲并處理。

(3)OnFocusChangeListener接口:此接口用于處理View組件焦點(diǎn)改變事件。當(dāng)View組件失去或獲得焦點(diǎn)時(shí)會(huì)觸發(fā)該事件,其對(duì)應(yīng)的回調(diào)方法為public void onFocusChange(View v, Boolean hasFocus),其中參數(shù)v表示產(chǎn)生事件的事件源,hasFocus表示事件源的狀態(tài),即是否獲得焦點(diǎn)。

(4)OnKeyListener接口:此接口用于對(duì)手機(jī)鍵盤事件進(jìn)行監(jiān)聽,當(dāng)View獲得焦點(diǎn)并且鍵盤被敲擊時(shí)會(huì)觸發(fā)該事件。其對(duì)應(yīng)的回調(diào)方法為public boolean onKey(View v, int keyCode, KeyEvent event),其中參數(shù)keyCode為鍵盤碼,參數(shù)event便為鍵盤事件封裝類的對(duì)象。

(5)OnTouchListener接口:此接口是用來處理手機(jī)屏幕事件,當(dāng)在View的范圍內(nèi)觸摸、按下、抬起、滑動(dòng)等動(dòng)作時(shí)都會(huì)觸發(fā)該事件,并觸發(fā)該接口中的回調(diào)方法,其對(duì)應(yīng)的回調(diào)方法:public boolean onTouch(View v, MotionEvent event)對(duì)應(yīng)的參數(shù)同上。

(6)OnCreateContextMenuListener接口:此接口用于處理上下文菜單被創(chuàng)建的事件,其對(duì)應(yīng)的回調(diào)方法為public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo info),其中參數(shù)menu為事件的上下文菜單,參數(shù)info是該對(duì)象中封裝了有關(guān)上下文菜單其他的信息。在4.5節(jié)的實(shí)例MenusDemo中,創(chuàng)建上下文菜單使用的是registerForContextMenu(View v)方法,其本質(zhì)是為View組件v注冊(cè)該接口,并實(shí)現(xiàn)了相應(yīng)的回調(diào)方法。

4.9.2 回調(diào)事件響應(yīng)

在Android框架中,除了可以使用監(jiān)聽器進(jìn)行事件處理之外,還可以通過回調(diào)機(jī)制進(jìn)行事件處理。Android SDK為View組件提供了五個(gè)默認(rèn)的回調(diào)方法,如果當(dāng)某個(gè)事件沒有被任意一個(gè)View處理,則會(huì)在Activity中調(diào)用響應(yīng)的回調(diào)方法,這些方法分別如下所示。

(1)public boolean onKeyDown(int keyCode, KeyEvent event)方法是接口KeyEvent.Callback中的抽象方法,當(dāng)鍵盤按鈕被按下時(shí)由系統(tǒng)調(diào)用。參數(shù)keyCode即鍵盤碼,系統(tǒng)根據(jù)鍵盤碼得知按下的是哪個(gè)按鈕。參數(shù)event為按鈕事件的對(duì)象,包含了觸發(fā)事件的詳細(xì)信息,例如事件的類型、狀態(tài)等。當(dāng)此方法的返回值為True時(shí),代表已完成處理此事件,返回false表示該事件還可以被其他監(jiān)聽器處理。

(2)public boolean onKeyUp(int keyCode, KeyEvent event)方法也是接口KeyEvent.Callback中的抽象方法,當(dāng)按鈕向上彈起時(shí)被調(diào)用,參數(shù)與onKeyDown()完全相同。

(3)public boolean onTouchEvent(MotionEvent event)方法在View中定義,當(dāng)用戶觸摸屏幕時(shí)被自動(dòng)調(diào)用。參數(shù)event為觸摸事件封裝類的對(duì)象,封裝了該事件的相關(guān)信息。當(dāng)用戶觸摸到屏幕,屏幕被按下時(shí),MotionEvent.getAction()的值為MotionEvent.ACTION_DOWN;當(dāng)用戶將觸控物體離開屏幕時(shí),MotionEvent.getAction()的值為MotionEvent.ACTION_UP;當(dāng)觸控物體在屏幕上滑動(dòng)時(shí),MotionEvent.getAction()的值為MotionEvent.ACTION_MOVE。onTouchEvent方法的返回值為true表示事件處理完成,返回false表示未完成。

(4)public boolean onTrackballEvent(MotionEvent event)方法的功能是處理手機(jī)中軌跡球的相關(guān)事件,可以在Activity中重寫,也可以在View中被重寫。參數(shù)event為手機(jī)軌跡球事件封裝類的對(duì)象。該方法的返回值為true表示事件處理完成,返回false表示未完成。

(5)protected void onFocusChanged(boolean gainFocus, int direction, Rect previously FocusedRect)方法只能在View中重寫,當(dāng)View組件焦點(diǎn)改變時(shí)被自動(dòng)調(diào)用,參數(shù)gainFocus表示觸發(fā)該事件的View是否獲得了焦點(diǎn),獲得焦點(diǎn)為true,參數(shù)direction表示焦點(diǎn)移動(dòng)的方向,參數(shù)previouslyFocusedRect是在觸發(fā)事件的View的坐標(biāo)系中前一個(gè)獲得焦點(diǎn)的矩形區(qū)域。

4.9.3 界面事件響應(yīng)實(shí)例

在之前的章節(jié)中,多次使用了監(jiān)聽器對(duì)事件進(jìn)行處理,讀者應(yīng)該已經(jīng)很熟悉了。本節(jié)通過一個(gè)實(shí)例來演示回調(diào)事件響應(yīng)的處理過程,該實(shí)例EventDemo運(yùn)行效果如圖4.50所示。

圖4.50 實(shí)例EventDemo運(yùn)行效果

其布局文件main.xml內(nèi)容如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">



       <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="回調(diào)事件處理演示" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
       <Button
         android:id="@+id/button1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:focusableInTouchMode="true"
         android:text="按鈕1"/>
     <Button
         android:id="@+id/button2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:focusableInTouchMode="true"
         android:text="按鈕2"/>
     <Button
         android:id="@+id/button3"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:focusableInTouchMode="true"
         android:text="按鈕3"/>
    </LinearLayout>



    </LinearLayout>

當(dāng)用戶在屏幕上做移動(dòng)觸摸、單擊按鈕等操作時(shí),主Activity EventDemo會(huì)捕獲相應(yīng)事件并進(jìn)行處理,在LogCat中打印相關(guān)內(nèi)容,運(yùn)行效果如圖4.51所示。

圖4.51 Activity EventDemo捕獲事件

EventDemo.java代碼如下:

    package introduction.android.eventDemo;



    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Rect;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.KeyEvent;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnFocusChangeListener;
    import android.widget.Button;
    import android.widget.Toast;



    public class EventDemo extends Activity implements OnFocusChangeListener {
        Button[] buttons=new Button[3];
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            buttons[0]=(Button)findViewById(R.id.button1);
            buttons[1]=(Button)findViewById(R.id.button2);
            buttons[2]=(Button)findViewById(R.id.button3);
            for(Button button :buttons){
                button.setOnFocusChangeListener(this);
            }
        }
        //按鈕按下觸發(fā)的事件
        public boolean onKeyDown(int keyCode,KeyEvent event)
        {
            switch(keyCode)
            {
                case KeyEvent.KEYCODE_DPAD_UP:
                    DisplayInformation("按下上方向鍵,KEYCODE_DPAD_UP");
                    break;
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    DisplayInformation("按下下方向鍵,KEYCODE_DPAD_UP");
                    break;
            }
            return false;
        }
        //按鈕彈起觸發(fā)的事件
        public boolean onKeyUp(int keyCode,KeyEvent event)
        {
            switch(keyCode)
            {
                case KeyEvent.KEYCODE_DPAD_UP:
                    DisplayInformation("松開上方向鍵,KEYCODE_DPAD_UP");
                    break;
                case KeyEvent.KEYCODE_DPAD_DOWN:
                    DisplayInformation("松開下方向鍵,KEYCODE_DPAD_UP");
                    break;
            }
            return false;



        }



        //觸摸事件
        public boolean onTouchEvent(MotionEvent event)
        {
            switch(event.getAction()){
      case MotionEvent.ACTION_DOWN:
        DisplayInformation("手指正在往屏幕上按下");
        break;
      case MotionEvent.ACTION_MOVE:
        DisplayInformation("手指正在屏幕上移動(dòng)");
        break;
      case MotionEvent.ACTION_UP:
        DisplayInformation("手指正在從屏幕上抬起");
        break;
      }
          return false;
        }



        //焦點(diǎn)事件
        @Override
        public void onFocusChange(View view, boolean arg1){
      switch(view.getId()){
      case R.id.button1:
        DisplayInformation("第一個(gè)按鈕獲得了焦點(diǎn)");
        break;
      case R.id.button2:
        DisplayInformation("第二個(gè)按鈕獲得了焦點(diǎn)");
        break;
      case R.id.button3:
        DisplayInformation("第三個(gè)按鈕獲得了焦點(diǎn)");
        break;
      }
        }



        //顯示Toast
        public void DisplayInformation(String string)
        {
            //Toast.makeText(EventDemo.this,string,Toast.LENGTH_SHORT).show();
        Log.i("enentDemo",string);
        }
    }
主站蜘蛛池模板: 忻城县| 唐海县| 元江| 仙居县| 澜沧| 康定县| 林甸县| 湾仔区| 广东省| 凉山| 延津县| 吉林省| 威海市| 郴州市| 金昌市| 滦南县| 张北县| 宁海县| 巩义市| 万年县| 郁南县| 临澧县| 衡阳县| 鄢陵县| 余江县| 西华县| 仪征市| 白山市| 渭南市| 北流市| 奉贤区| 大宁县| 夏河县| 永福县| 平乐县| 平陆县| 元谋县| 济源市| 金塔县| 太湖县| 宾川县|