- Android經(jīng)典應(yīng)用程序開發(fā)
- 韓超編著
- 1180字
- 2019-01-09 15:18:45
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ū)分。
- Premiere Pro與After Effects從入門到實(shí)戰(zhàn)(微課版)
- 構(gòu)建運(yùn)營(yíng)級(jí)IPv6網(wǎng)絡(luò)
- 通信網(wǎng)圖論及應(yīng)用
- 衛(wèi)星通信干擾感知及智能抗干擾技術(shù)
- 圖解電子技術(shù)速學(xué)速用
- Protel DXP 2004 SP2原理圖與PCB設(shè)計(jì)
- 深入理解Android:Java虛擬機(jī)ART
- 怎樣識(shí)別和檢測(cè)電子元器件(第2版)
- 無線定位系統(tǒng)
- 5G移動(dòng)通信:無線網(wǎng)絡(luò)優(yōu)化技術(shù)與實(shí)踐
- 5G網(wǎng)絡(luò)技術(shù)與規(guī)劃設(shè)計(jì)基礎(chǔ)
- 電子裝聯(lián)中的無鉛焊料
- iOS開發(fā)快速進(jìn)階與實(shí)戰(zhàn)
- 綠色數(shù)據(jù)中心基礎(chǔ)設(shè)施建設(shè)及應(yīng)用指南
- 信息的傳輸與通信技術(shù)