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

2.2 屏幕中內(nèi)容的控制和響應(yīng)

Android屏幕中的內(nèi)容是android.view.View類的繼承者。按照通常的概念,這些View的繼承者可以稱為控件。對(duì)于屏幕中內(nèi)容(控件)的控制和響應(yīng)是GUI系統(tǒng)最基礎(chǔ)的內(nèi)容。

程序中,對(duì)于屏幕中內(nèi)容(控件)的控制和響應(yīng)的兩個(gè)使用要點(diǎn)為:

獲得控件句柄;

定制控件的行為;

在Android中,得到控件的句柄通常是由id屬性來指定的。在布局文件中,用于指定id的XML屬性為android:id。

findViewById()方法用于得到一個(gè)控件句柄,其參數(shù)為控件的id,方法如下所示:

        public View findViewById (int id)

findViewById()是View和Activity都具有的方法,對(duì)于View表示獲得其某個(gè)子控件句柄,對(duì)于Activity,表示獲得其中內(nèi)容視圖(ContentView)的某個(gè)子控件句柄。

定制控件的行為,通常需要使用View類中的SetOn{XXX}Listener()系列方法,設(shè)置的內(nèi)容也就是前面所述的android.view包中的幾個(gè)接口。這個(gè)方法可以在每一個(gè)繼承View控件中被調(diào)用。

2.2.1 基本響應(yīng)方法

本節(jié)介紹Android中的幾種基本的程序控制方法,要獲得的效果是通過兩個(gè)按鈕來控制一個(gè)文本框的文字和字體顏色,其運(yùn)行結(jié)果如圖2-3所示。

圖2-3 控件事件的響應(yīng)運(yùn)行結(jié)果

本例構(gòu)建一個(gè)應(yīng)用程序,TestEvent1是活動(dòng)的名稱,res/layout目錄中的testevent.xml是界面布局文件。本例布局文件的代碼如下所示:

        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/screen"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">
            <TextView android:id="@+id/text1"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:textSize="24sp"
              android:text="@string/text1" />
            <Button android:id="@+id/button1"
              android:layout_width="80sp"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:text="@string/red"/>
            <Button android:id="@+id/button2"
              android:layout_width="80sp"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:text="@string/green"/>
        </LinearLayout>

以上布局文件中定義了兩個(gè)按鈕和一個(gè)文本框,這個(gè)布局文件被活動(dòng)設(shè)置為Vi e w后,顯示的內(nèi)容就如圖2-2所示,只是行為還沒有實(shí)現(xiàn)。

行為將在源代碼文件TestEvent1.java中實(shí)現(xiàn),這部分的代碼如下所示:

        import android.app.Activity;
        import android.os.Bundle;
        import android.graphics.Color;
        import android.widget.Button;
        import android.widget.TextView;
        import android.view.View;
        import android.view.View.OnClickListener;
        import android.util.Log;
        public class TestEvent1 extends Activity {
            private static final String TAG = "TestEvent1";
            public TestEvent1() {
            }
            @Override
            public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.testevent);
              final TextView Text = (TextView) findViewById(R.id.text1);   // 獲得句柄
              final Button Button1 = (Button) findViewById(R.id.button1);
              final Button Button2 = (Button) findViewById(R.id.button2);
              Button1.setOnClickListener(new OnClickListener() { // 實(shí)現(xiàn)行為功能
                  public void onClick(View v) {
                      Text.setTextColor(Color.RED);      // 設(shè)置文本和文本顏色為“紅”
                      Text.setText("RED");
                  }
              });
              Button2.setOnClickListener(new OnClickListener() {
                  public void onClick(View v) {
                      Text.setTextColor(Color.GREEN);    // 設(shè)置文本和文本顏色為“綠”
                      Text.setText("GREEN");
                  }
              });
            }
        }

在創(chuàng)建的過程中,通過findViewById()獲得各個(gè)屏幕上面的控件(控件)的背景,這里使用的R.id.button1等和布局文件中各個(gè)元素的id是對(duì)應(yīng)的。在布局文件中即使不寫android:id這一項(xiàng)也可以正常顯示,這一項(xiàng)的目的是在代碼中對(duì)其進(jìn)行控制:通過Activity的findViewById()方法根據(jù)id獲得每一個(gè)控件的句柄,以View類型返回,可以轉(zhuǎn)換成實(shí)際的類型來使用。

Button控件的setOnClickListener()設(shè)置了其中的點(diǎn)擊行為,這個(gè)方法的參數(shù)實(shí)際上是一個(gè)View.OnClickListener類型的接口,這個(gè)接口需要被實(shí)現(xiàn)才能夠使用,因此在本例的設(shè)置中,實(shí)現(xiàn)了其中的onClick()方法。這樣即可在點(diǎn)擊的時(shí)候?qū)崿F(xiàn)相應(yīng)的功能,在點(diǎn)擊的方法中,將通過Te x t的句柄對(duì)其進(jìn)行控制。

在獲取句柄時(shí)需要轉(zhuǎn)換成相應(yīng)的控件類型,findViewById()方法的參數(shù)是一個(gè)整數(shù),返回值是View類型。通過R.id.XXX找到布局文件中定義的ID,然后通過將基類View轉(zhuǎn)換成其實(shí)際的類獲得真正的句柄??丶D(zhuǎn)換類應(yīng)該和布局文件中描述的控件一致,如果轉(zhuǎn)換成這個(gè)類的祖先類,將會(huì)損失部分繼承者自身功能,如果轉(zhuǎn)換成非祖先類并調(diào)用其中的方法將會(huì)錯(cuò)誤。

提示:在代碼中使用R.id.myid的時(shí)候,如果當(dāng)前包中根本沒有myid這個(gè)id,編譯將報(bào)錯(cuò)。但是如果這個(gè)包中的其他布局文件中生成myid這個(gè)id,但當(dāng)前布局文件中沒有這個(gè)id,編譯不會(huì)報(bào)錯(cuò),運(yùn)行時(shí)將會(huì)返回null,造成運(yùn)行錯(cuò)誤。

2.2.2 變化的響應(yīng)方法

在實(shí)現(xiàn)控件行為方面,除了上述的使用方法,根據(jù)Java的語(yǔ)法,還具有其他的實(shí)現(xiàn)方式。第二種響應(yīng)方法可以將不同控件的同一種行為聚集到一個(gè)方法的實(shí)現(xiàn)中;第三種響應(yīng)方法可以為一個(gè)控件單獨(dú)實(shí)現(xiàn)一個(gè)響應(yīng)。

1.第二種響應(yīng)方法:由Activity實(shí)現(xiàn)某接口

對(duì)控件的響應(yīng)可以由Activity類來實(shí)現(xiàn)某個(gè)Listener接口,完成其中的方法,然后將其設(shè)置為某個(gè)控件的監(jiān)聽者,以此得到對(duì)控件的響應(yīng)。

以下程序使用的是上述實(shí)現(xiàn)方式,在使用同樣的布局文件的情況下,本例使用的源代碼文件如下所示:

        import android.app.Activity;
        import android.os.Bundle;
        import android.graphics.Color;
        import android.widget.Button;
        import android.widget.TextView;
        import android.view.View;
        import android.view.View.OnClickListener;
        import android.util.Log;
        public class TestEvent2 extends Activity
                                  implements OnClickListener {      // 實(shí)現(xiàn)相關(guān)的接口
            private static final String TAG = "TestEvent2";
            private TextView mText;                                 // 保存控件類的引用
            private Button mButton1;
            private Button mButton2;
            public TestEvent2() {
            }
            @Override
            public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.testevent);
              mText = (TextView) findViewById(R.id.text1);
              mButton1 = (Button) findViewById(R.id.button1);
              mButton1.setOnClickListener(this);        // 設(shè)置監(jiān)聽者為TestEvent2
              mButton2 = (Button) findViewById(R.id.button2);
              mButton2.setOnClickListener(this);        // 設(shè)置監(jiān)聽者為TestEvent2
            }
            public void onClick(View v) {
              Log.v(TAG, "onClick()");
              switch(v.getId()){                         // 通過getId()區(qū)分不同的控件
                  case R.id.button1:
                      mText.setTextColor(Color.RED);      // 設(shè)置文本和文本顏色為“紅”
                      mText.setText("RED");
                      break;
                  case R.id.button2:
                      mText.setTextColor(Color.GREEN);    // 設(shè)置文本和文本顏色為“綠”
                      mText.setText("GREEN");
                      break;
                  default:
                      Log.v(TAG, "other");
                      break;
              }
            }
        }

這個(gè)例子的主要變化是讓活動(dòng)實(shí)現(xiàn)了(implements)OnClickListener()這個(gè)接口,也就是需要實(shí)現(xiàn)其中的onClick()方法。然后通過setOnClickListener()將其設(shè)置到按鈕中的參數(shù)就是this,表示了當(dāng)前的活動(dòng)。

通過以這種方式設(shè)置,如果程序中有多個(gè)控件需要設(shè)置,那么所設(shè)置的也都是一個(gè)方法。為了保證對(duì)不同控件有不同的處理,可以由onClick()方法的參數(shù)進(jìn)行判斷,參數(shù)是一個(gè)View類型,通過getId()獲得它們的ID,使用switch…case分別進(jìn)行處理。

在本例中,需要將文本框(TextView)句柄保存為類的成員(mText),這樣就可以在類的各個(gè)方法中都能獲得這個(gè)句柄進(jìn)行處理。這和第一種方法是有區(qū)別的,因?yàn)榈谝粋€(gè)例子實(shí)現(xiàn)的接口和獲得的TextView在同一個(gè)方法中,因此不需要保存TextView的句柄,只需要使用final的局部變量即可。

2.第三種響應(yīng)方法:構(gòu)建一個(gè)類實(shí)現(xiàn)某接口

在響應(yīng)控件事件方面,一種最為直接的方法是:構(gòu)建一個(gè)類實(shí)現(xiàn)所需要的Listener接口,創(chuàng)建這個(gè)類的實(shí)例之后,將其設(shè)置到控件中。

以下為同樣功能的第三種實(shí)現(xiàn)方法,在布局文件相同的情況下,Java源代碼的內(nèi)容如下所示:

        package com.android.basicapp;
        import android.app.Activity;
        import android.os.Bundle;
        import android.graphics.Color;
        import android.widget.Button;
        import android.widget.TextView;
        import android.view.View;
        import android.view.View.OnClickListener;
        import android.util.Log;
        public class TestEvent3 extends Activity{
            private static final String TAG = "TestEvent3";
            private TextView mText;
            private Button1_OnClickListener mListener1 = new Button1_Listener();
            private Button2_OnClickListener mListener2 = new Button2_Listener();
            public TestEvent3() {
            }
            class Button1_Listener implements OnClickListener { // 接口的第一個(gè)實(shí)現(xiàn)
              public void onClick(View v) {
                      mText.setTextColor(Color.RED);     // 設(shè)置文本和文本顏色為“紅”
                      mText.setText("RED");
              }
            }
            class Button2_Listener implements OnClickListener {   // 接口的第一個(gè)實(shí)現(xiàn)
              public void onClick(View v) {
                      mText.setTextColor(Color.GREEN);              //設(shè)置文本和文本顏色為“綠”
                      mText.setText("GREEN");
              }
            }
            @Override
            public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.testevent);
              mText = (TextView) findViewById(R.id.text1);
              final Button mButton1 = (Button) findViewById(R.id.button1);
              final Button mButton2 = (Button) findViewById(R.id.button2);
              mButton1.setOnClickListener(mListener1);  // 設(shè)置監(jiān)聽者的類
              mButton2.setOnClickListener(mListener2);  // 設(shè)置監(jiān)聽者的類
            }
        }

本例通過定義實(shí)現(xiàn)活動(dòng)類中的兩個(gè)子類,來實(shí)現(xiàn)View.OnClickListener這個(gè)接口,這種方式是一種最為直接的方式,即為不同的控件單獨(dú)實(shí)現(xiàn)它的相應(yīng)類。

使用這種實(shí)現(xiàn)方法,如果由一個(gè)類繼承若干個(gè)Listener接口,可以讓其實(shí)現(xiàn)多個(gè)不同的行為。實(shí)現(xiàn)同時(shí)點(diǎn)擊和長(zhǎng)按事件的方法如下所示:

        class MyListener implements OnClickListener,OnLongClickListener {
            public void onClick(View v) {
              // ......點(diǎn)擊事件的實(shí)現(xiàn)
            }
            public boolean onLongClick(View v){
              // ......長(zhǎng)按事件的實(shí)現(xiàn)
            }
        }

隨后可以調(diào)用setOnClickListener()和setOnLongClickListener()將這個(gè)監(jiān)聽者的實(shí)現(xiàn)設(shè)置到某個(gè)控件當(dāng)中。這種方式尤其適合一個(gè)控件需要定制多個(gè)行為,并且可能多個(gè)行為之間還有共同處理(例如,調(diào)用同一個(gè)方法)的場(chǎng)合。

2.2.3 控件響應(yīng)方法比較

以上列出了在Java代碼中對(duì)控件事件做出響應(yīng)的三種方法,比較這三種方法,分別具有以下的特點(diǎn)。

第一種方法利用Java的語(yǔ)法,將所有內(nèi)容都組織到一個(gè)方法當(dāng)中。這種方法雖然看似簡(jiǎn)單,但是這種程序的結(jié)構(gòu)性并不好。

第二種方法將不同控件的同一種行為聚集到一個(gè)方法中:只需要實(shí)現(xiàn)一個(gè)接口中的方法,就可以為所有控件使用。

第三種方法可以將同一個(gè)控件的不同行為聚集到一個(gè)類當(dāng)中。如果構(gòu)建一個(gè)類讓其繼承多個(gè)Listener,并實(shí)現(xiàn)其中的方法,可以同時(shí)完成對(duì)多個(gè)行為的響應(yīng)。

在實(shí)際的應(yīng)用場(chǎng)景中,由于多個(gè)同類控件響應(yīng)同一種行為的情況比較多見,因此在Android應(yīng)用程序的實(shí)現(xiàn)中,第二種方法的使用比第三種方法多。

如果同一個(gè)布局中控件的id有所重復(fù),即多個(gè)控件使用相同的id,在這種情況下,第二種方法的switch…case將不太容易區(qū)分每個(gè)控件。這時(shí)可以考慮使用第三種方法,自己實(shí)現(xiàn)不同的類,在設(shè)置監(jiān)聽器的階段對(duì)不同控件做出區(qū)分。

主站蜘蛛池模板: 南澳县| 江北区| 鹿邑县| 溧阳市| 江达县| 龙口市| 和政县| 开封县| 合水县| 阳谷县| 大名县| 获嘉县| 扎囊县| 榆中县| 清丰县| 泽普县| 富锦市| 荆州市| 忻州市| 文水县| 安新县| 长乐市| 四会市| 岗巴县| 六枝特区| 日土县| 三穗县| 新晃| 滨州市| 黄浦区| 山阴县| 衡水市| 调兵山市| 新巴尔虎左旗| 江西省| 和静县| 蓝山县| 休宁县| 闽侯县| 温宿县| 定西市|