- Android 5從入門到精通
- 李波
- 9384字
- 2021-03-19 15:29:02
4.4 常用Widget組件
在前面章節的學習中講解了用戶界面UI設計中布局方面的知識,其中涉及少數幾個常用的組件,例如按鈕、文本框等。在這一節中著重講解Android用戶UI設計中常用的各種組件的用法。
Android SDK提供了名為android.widget的包,其中提供了在應用程序界面設計中大部分常用的UI可視組件。之前章節中涉及的各種布局以及文本框、按鈕等組件,都包含在這個包中。Android提供了強大的用戶UI功能,要設計自己獨特的應用程序界面,需要對各個組件有一個詳細的了解。
4.4.1 創建Widget組件實例
在Eclipse中創建一個新的工程,名字為WidgetDemo,用于對各種常見UI組件進行學習。下面是工程實現步驟,在后續的章節中不會再贅述該過程:
步驟01 新建項目。單擊File | New | Android Project,打開New Android Projec對話框,如圖4.12所示。

圖4.12 新建項目
步驟02 輸入工程名稱WidgetDemo,在Location后的文本框中輸入工程的保存路徑,單擊Next后選擇Android4.0,單擊Next。
步驟03 輸入包名“introduction.android.widgetDemo”和Activity的名稱WidgetDemoActivity,單擊Finish,則Eclipse會生成工程目錄和相關文件。
WidgetDemoActivity.java文件是當前應用程序的入口類WidgetDemoActivity的定義文件。雙擊WidgetDemoActivity.java,發現Eclipse已經為其生成代碼如下:
package introduction.android.widgetDemo; import android.app.Activity; import android.os.Bundle; public class WidgetDemoActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); } }
其中onCreate()方法中的setContentView(R.layout.main)表明WidgetDemoActivity使用的用戶界面UI文件為main.xml。
雙擊main.xml文件,發現Eclipse為其提供了“Graphical Layout”和“main.xml”兩種瀏覽方式。其中“Graphical Layout”方式為以圖形方式瀏覽main.xml文件,其效果等同于main.xml在手機設備上運行的效果;“main.xml”方式為以代碼方式瀏覽main.xml文件。這兩種方式是等效的,都可以對main.xml文件進行編輯和查看。單擊“main.xml”標簽,發現Eclipse已經為其生成代碼如下:
<?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="@string/hello" /> </LinearLayout>
該文件表明,當前main.xml文件所使用的布局為LinearLayout布局,該布局自動填滿整個手機屏幕。在該布局中,放置了一個TextView組件,該TextView顯示的內容為"@string/hello",表示string.xml文件中定義的hello變量的內容。雙擊values目錄下的string.xml文件,會發現hello變量對應的值為“Hello World, WidgetDemoActivity!”。
單擊main.xml的“Graphical Layout”瀏覽方式,可查看當前文件的圖形化效果,如圖4.13所示。

圖4.13 文件的圖形化效果
程序開發人員可以在該圖形方式下,將左側的各種組件直接拖動到屏幕上形成自己想要的布局,也可以直接修改main.xml文件的代碼。
在后續章節中,在對布局文件進行修改時,若非特殊情況將不再單獨描述。
4.4.2 按鈕(Button)
Button按鈕應該是用戶交互中使用最多的組件,在很多應用程序中都很常見。當用戶單擊按鈕的時候,會有相對應的響應動作。下面在WidgetDemo工程的主界面中main.xml中放置一個名為Button的按鈕。文件代碼如下:
<?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="@string/hello" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout>
其中,
<Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" />
表明在用戶界面上放置了一個id為“button1”的按鈕,按鈕的高度(layout_height)和寬度(layout_width)都會根據實際內容調整(wrap_content),按鈕上顯示文字為Button,其運行效果如圖4.14所示。

圖4.14 Button的應用界面
按鈕最重要的用戶交互事件是“單擊”事件。下面為Button1添加事件監聽器和相應的單擊事件。該過程在WidgetDemoActivity.java文件中完成,代碼如下:
package introduction.android.widgetDemo; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class WidgetDemoActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btn=(Button)this.findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub setTitle("button1 被用戶點擊了"); Log.i("widgetDemo", "button1 被用戶點擊了。"); } }); } }
在WidgetDemoActivity的onCreate()方法中,通過findViewById(R.id.button1)方法獲得的Button1的對象,通過setOnClickListener()方法為Button1設置了監聽器。此處新建了一個實現了OnClickListener接口的匿名類作為監聽器,并實現了onClick()方法。當Button1被單擊,當前應用程序的標題被設置成“button1被用戶單擊了”,對應在LogCat中也會打印相應的字符串,運行結果如圖4.15所示。

圖4.15 單擊按鈕運行效果
4.4.3 文本框(TextView)
TextView是用于在界面上顯示文字的組件,其顯示的文本不可被用戶直接編輯。程序開發人員可以設置TextView字體大小、顏色、樣式等屬性。在工程WidgetDemo的main.xml中添加一個TextView,代碼如下:
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" />
運行效果如圖4.16所示。

圖4.16 TextView的應用界面
修改Button1的單擊事件為:
public void onClick(View view){ // TODO Auto-generated method stub //setTitle("button1 被用戶單擊了"); Log.i("widgetDemo", "button1 被用戶單擊了。"); TextView textview=(TextView)findViewById(R.id.textView1); textview.setText("設置TextView的字體"); textview.setTextColor(Color.RED); textview.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20); textview.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); }
當Button1被單擊時,通過setText()方法更改textView的顯示內容為“設置TextView的字體”,通過setTextColor()方法修改textView顯示字體的顏色為紅色,通過setTextSize()方法修改textView顯示字體的大小為20sp,通過setTypeface()方法修改textView顯示字體的風格為加粗。

圖4.17 再次單擊按鈕運行效果
當然,該過程也可以通過修改main.xml文件來實現。將TextView標簽按照如下代碼修改也可得到同樣效果,但是失去了應用程序中與用戶交互的過程:
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="設置TextView的字體" android:textColor="#ff0000" android:textSize="20sp" android:textStyle="bold"/>
4.4.4 編輯框(EditText)
EditText是TextView的子類,在TextView的基礎上增加了文本編輯功能,用于處理用戶輸入,例如登錄框等,是非常常用的組件。
在工程WidgetDemo的main.xml文件中添加一個EditText,并實現如下功能:當用戶在EditText中輸入信息的同時,用一個TextView顯示用戶輸入的信息。
工程WidgetDemo中的布局文件main.xml中增加的代碼如下:
<EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content">
在WidgetDemoActivity的onCreate()方法中添加下列代碼:
editText=(EditText)findViewById(R.id.editText1); editText.addTextChangedListener(new TextWatcher(){ @Overridepublic void afterTextChanged(Editable s){ // TODO Auto-generated method stub } @Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after){ // TODO Auto-generated method stub } @Overridepublic void onTextChanged(CharSequence s, int start, int before, int count){ // TODO Auto-generated method stub String text=editText.getText().toString(); textview.setText(text); } });
運行結果如圖4.18所示。

圖4.18 EditText的應用界面
4.4.5 多項選擇按鈕(CheckBox)
多項選擇按鈕CheckBox屬于輸入型組件,該組件允許用戶一次選擇多個選項。當不方便用戶在手機屏幕上進行直接輸入操作時,該組件的使用顯得尤為便利。
下面通過實例講解CheckBox的使用方法。該實例運行效果如圖4.19所示。

圖4.19 CheckBox的應用界面
在工程WidgetDemo的布局文件main.xml文件中添加一個Button,代碼如下:
<Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="CheckBoxDemo" />
當該Button被用戶單擊時,啟動一個名為CheckBoxActivity的Activity,在該Activity中演示CheckBox的使用方法。啟動CheckBoxActivity的相關代碼如下:
Button ckbtn=(Button)this.findViewById(R.id.button2); ckbtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,CheckBoxActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name="CheckBoxActivity"></activity>
CheckBoxActivity所使用的布局文件為checkbox.xml,使用LinearLayout布局,其中放置了一個TextView和三個CheckBox。Checkbox.xml的文件內容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/checkboxhello"/> <CheckBox android:id="@+id/CheckBox1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/football"/> <CheckBox android:id="@+id/CheckBox2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/song"/> <CheckBox android:id="@+id/CheckBox3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/book"/> </LinearLayout>
這四個組件在對應的strings.xml文件中定義的變量為:
<string name="checkboxhello">你的愛好是:</string> <string name="football">籃球</string> <string name="song">聽歌曲</string> <string name="book">看書</string>
當用戶對多項選擇按鈕進行選擇時,為了確定用戶選擇的是哪幾項,需要對每個多項選擇按鈕進行監聽。CompouButton.OnCheckedChangedListener接口可用于對CheckBox的狀態進行監聽。當CheckBox的狀態在未被選中和被選中直接變化時,該接口的onCheckedChanged()方法會被系統調用。CheckBox通過setOnCheckedChangeListener()方法將該接口對象設置為自己的監聽器。
CheckBoxActivity.java代碼如下:
package introduction.android.widgetDemo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
public class CheckBoxActivity extends Activity {
private TextView textView;
private CheckBox bookCheckBox;
private CheckBox songCheckBox;
private CheckBox footbaCheckBox;
@Override
protected void onCreate(Bundle savedInstanceState){
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.checkbox);
textView=(TextView)findViewById(R.id.text);
footbaCheckBox=(CheckBox)findViewById(R.id.CheckBox1);
songCheckBox=(CheckBox)findViewById(R.id.CheckBox2);
bookCheckBox=(CheckBox)findViewById(R.id.CheckBox3);
footbaCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
// TODO Auto-generated method stub
if(footbaCheckBox.isChecked()){
textView.append(footbaCheckBox.getText().toString());
}else {
if(textView.getText().toString().contains("足球")){
textView.setText(textView.getText().toString().replace("足球", ""));
}
}
}
});
songCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
// TODO Auto-generated method stub
if(songCheckBox.isChecked()){
textView.append(songCheckBox.getText().toString());
}else {
if(textView.getText().toString().contains("唱歌")){
textView.setText(textView.getText().toString().replace("唱歌", ""));
}
}
}
});
bookCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
// TODO Auto-generated method stub
if(bookCheckBox.isChecked()){
textView.append(bookCheckBox.getText().toString());
}else {
if(textView.getText().toString().contains("讀書")){
textView.setText(textView.getText().toString().replace("讀書", ""));
}
}
}
});
}
}
CheckBoxActivity為Checkbox.xml文件中的三個CheckBox分別添加了監聽器。當CheckBox的狀態發生改變時,通過Checkbox.isChecked()方法可以獲取當前CheckBox按鈕的選中狀態,進而進行處理。
4.4.6 單項選擇按鈕組(RadioGroup)
RadioGroup為單選按鈕組,其中可以包含多個RadioButton,即單選按鈕,它們共同為用戶提供一種多選一的選擇方式。在多個RadioButton被同一個RadioGroup包含的情況下,多個RadioButton之間自動形成互斥關系,僅有一個可以被選擇。單選按鈕的使用方法和CheckBox的使用方法高度相似,其事件監聽接口使用的是RadioGroup.OnCheckedChangeListener(),使用setOnCheckedChangeListener()方法將監聽器設置到單選按鈕上。按照CheckBox的講解思路,啟動一個名為RadioGroupActivity的Activity來對RadioGroup進行講解。
RadioGroupActivity運行效果如圖4.20所示。

圖4.20 RadioGroup的應用界面
在工程WidgetDemo的布局文件main.xml文件中添加一個Button,并啟動RadioGroupActivity的相關代碼。在main.xml中添加代碼如下:
<Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioGroupDemo" />
啟動處理RadioGroup的Activity RadioGroupActivity的代碼如下:
Button radiotn=(Button)this.findViewById(R.id.button3); radiotn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,RadioGroupActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name=" RadioGroupActivity "></activity>
RadioGroupActivity使用的是radiogroup.xml,其代碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/radiohello" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"/> <RadioGroup android:id="@+id/radiogroup1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_x="3px" > <RadioButton android:id="@+id/radiobutton1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/football" /> <RadioButton android:id="@+id/radiobutton2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/bascketball" /> <RadioButton android:id="@+id/radiobutton3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/badminton" /> </RadioGroup> </LinearLayout>
該布局文件使用了LinearLayout布局,并且在其中放置了一個TextView和一個RadioGroup。RadioGroup中含有三個RadioButton。這些組件對應的strings.xml文件中定義的變量為:
<string name="radiohello">你最喜歡的運動是:</string> <string name="bascketball">籃球</string> <string name="badminton">羽毛球</string> <string name="football">足球</string>
RadioGroupActivity.java代碼如下:
package introduction.android.widgetDemo; import android.app.Activity; import android.os.Bundle; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.TextView; public class RadioGroupActivity extends Activity { private TextView textview; private RadioGroup radiogroup; private RadioButton radio1,radio2,radio3; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.radiogroup); textview=(TextView)findViewById(R.id.radiohello); radiogroup=(RadioGroup)findViewById(R.id.radiogroup1); radio1=(RadioButton)findViewById(R.id.radiobutton1); radio2=(RadioButton)findViewById(R.id.radiobutton2); radio3=(RadioButton)findViewById(R.id.radiobutton3); radiogroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){ @Override public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub String text="我最喜歡的運動是"; if(checkedId==radio1.getId()){ text+=radio1.getText().toString(); textview.setText(text); }else if(checkedId==radio2.getId()){ text+=radio2.getText().toString(); textview.setText(text); }else if(checkedId==radio3.getId()){ text+=radio3.getText().toString(); textview.setText(text); } } }); } }
在RadioGroupActivity的onCreate()方法中為RadioGroup添加監視器RadioGroup。OnCheckedChangeListener,在其回調方法onCheckedChanged()中對三個RadioButton分別進行處理。需要說明的是如果把RadioGroup去掉,只使用RadioButton的話,則需要為每個RadioButton單獨設置監聽器,其使用方法和CheckBox沒有任何區別。
4.4.7 下拉列表(Spinner)
Spinner提供下拉列表式的輸入方式,該方法可以有效節省手機屏幕上的顯示空間。
下面用一個簡單的實例講解Spinner的使用方法。在工程WidgetDemo的布局文件main.xml文件中添加一個Button,用以啟動SpinnerActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="SpinnerDemo" />
單擊Button并啟動SpinnerActivity的代碼如下:
Button spinnerbtn=(Button)this.findViewById(R.id.button4); spinnerbtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,SpinnerActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name=" SpinnerActivity "></activity>
SpinnerActivity的運行效果如圖4.21所示。

圖4.21 Spinner的應用界面
SpinnerActivity使用的布局文件為spiner.xml,其代碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="textview"/> <Spinner android:id="@+id/spinner1" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
SpinnerActivity.java文件代碼如下:
package introduction.android.widgetDemo; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; public class SpinnerActivity extends Activity { private List<String>list=new ArrayList<String>(); private TextView textview; private Spinner spinnertext; private ArrayAdapter<String>adapter; public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.spiner); //第一步:定義下拉列表內容 list.add("沈陽"); list.add("天津"); list.add("北京"); list.add("上海"); list.add("深圳"); textview=(TextView)findViewById(R.id.textView1); spinnertext=(Spinner)findViewById(R.id.spinner1); //第二步:為下拉列表定義一個適配器 adapter=new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, list); //第三步:設置下拉列表下拉時的菜單樣式。 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //第四步:將適配器添加到下拉列表上 spinnertext.setAdapter(adapter); //第五步:添加監聽器,為下拉列表設置事件的響應 spinnertext.setOnItemSelectedListener(new Spinner.OnItemSelectedListener(){ public void onItemSelected(AdapterView<?>arg0, View arg1, int arg2, long arg3){ // TODO Auto-generated method stub /* 將所選spinnertext的值帶入myTextView 中*/ textview.setText("我來自:"+adapter.getItem(arg2)); /* 將spinnertext顯示*/ arg0.setVisibility(View.VISIBLE); } public void onNothingSelected(AdapterView<?>arg0){ // TODO Auto-generated method stub textview.setText("NONE"); arg0.setVisibility(View.VISIBLE); } }); //將spinnertext添加到OnTouchListener 對內容選項觸屏事件處理 spinnertext.setOnTouchListener(new Spinner.OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event){ // TODO Auto-generated method stub // 將mySpinner 隱藏 v.setVisibility(View.INVISIBLE); Log.i("spinner","Spinner Touch事件被觸發!"); return false; } }); //焦點改變事件處理 spinnertext.setOnFocusChangeListener(new Spinner.OnFocusChangeListener(){ public void onFocusChange(View v, boolean hasFocus){ // TODO Auto-generated method stub v.setVisibility(View.VISIBLE); Log.i("spinner","Spinner FocusChange 事件被觸發!"); } }); } }
SpinnerActivity通過五個步驟將Spinner初始化并進行事件處理。分別為:
●定義下拉列表的列表項內容List<String>。
●為下拉列表Spinner定義一個適配器ArrayAdapter<String>,并與列表項內容相關聯。
●使用ArrayAdapter.setDropDownViewResource()設置Spinner下拉列表在打開時的下拉菜單樣式。
●使用Spinner. setAdapter()將適配器數據與Spinner關聯起來。
●為Spinner添加事件監聽器,進行事件處理。
Spinner支持多種事件處理方式,本實例中對Spinner被單擊事件、焦點改變事件和Spinner的列表項被選中事件進行了處理。
在本實例中,SpinnerActivity在程序代碼中動態建立了下拉列表每一項的內容。除此之外,還可以在XML文件中定義Spinner的下拉列表項,步驟如下:
在res/values文件夾下新建cities.xml文件夾:
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="city"> <item>shenyang</item> <item>nanjing</item> <item>beijing</item> <item>tianjin</item> </string-array> </resources>
在SpinnerActivity.java中初始化Spinner:
Spinner spinner=(Spinner)findViewById(R.id.spinner1); ArrayAdapter<CharSequence>adapter=ArrayAdapter.createFromResource(this, R.array.city, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter);
運行效果如圖4.22所示。

圖4.22 Spinner的事件處理
4.4.8 自動完成文本(AutoCompleteTextView)
在使用百度或者Google搜索信息時,只需要在搜索框中輸入幾個關鍵字,就會有很多相關的信息以列表形式被列舉出來供用戶選擇,這種效果在Android SDK中可以通過AutoCompleteTextView來實現。
下面用一個簡單的實例講解AutoCompleteTextView的使用方法。在工程WidgetDemo的布局文件main.xml中添加一個Button,用以啟動AutoCompleteTextViewActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="AutoCompleteTextViewDemo" />
單擊Button,并啟動AutoCompleteTextViewActivity的代碼如下:
Button autobtn=(Button)this.findViewById(R.id.button5); autobtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,AutoCompleteTextViewActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name=" AutoCompleteTextViewActivity"></activity>
AutoCompleteTextViewActivity運行效果如圖4.23所示。

圖4.23 AutoCompleteTextViewActivity運行效果
AutoCompleteTextViewActivity使用的布局文件為autocompletetextview.xml,其具體內容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="AutoCompleteTextView演示:" /> <AutoCompleteTextView android:id="@+id/autoCompleteTextView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text=""> <requestFocus /> </AutoCompleteTextView> </LinearLayout>
AutoCompleteTextViewActivity.java代碼如下:
package introduction.android.widgetDemo; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; public class AutoCompleteTextViewActivity extends Activity { private AutoCompleteTextView textView; private static final String[] autotext=new String[] {"hello","hello World","hello Android"}; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.autocompletetextview); textView=(AutoCompleteTextView )findViewById(R.id.autoCompleteTextView1); /*new ArrayAdapterd對象將autotext字符串數組傳入*/ ArrayAdapter<String>adapter=new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,autotext); /*將ArrayAdapter添加到AutoCompleteTextView中*/ textView.setAdapter(adapter); } }
AutoCompleteTextViewActivity中為可自動補全的內容建立對應字符串數組autotext,然后將該數組關聯到ArrayAdapter中,然后將ArrayAdapter與AutoCompleteTextView相關聯,進而實現自動完成文本功能。
AutoCompleteTextView提供一系列屬性對顯示效果進行設置,例如:
●completionThreshold:它的值決定了你在AutoCompleteTextView至少輸入幾個字符,它才會具有自動提示的功能。另外默認最多提示20條。
●dropDownAnchor:它的值是一個View的ID,指定后,AutoCompleteTextView會在這個View下彈出自動提示。
●dropDownSelector:設置自動提示項中當前選中項的背景色。
●dropDownWidth:設置自動提示列表的寬度。
4.4.9 日期選擇器和時間選擇器(DatePicker和TimePicker)
Android SDK提供了DatePicker和TimePicker組件,分別對日期和時間進行選擇,方便日期和時間設定。
下面用一個簡單的實例講解DatePicker和TimePicker組件的使用方法。在工程WidgetDemo的布局文件main.xml中添加一個名為“Date/Time”的Button,用以啟動TimeActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" Date/Time " />
單擊Button并啟動TimeActivity的代碼如下:
Button timebtn=(Button)this.findViewById(R.id.button6); timebtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,TimeActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name=" TimeActivity"></activity>
TimeActivity運行效果如圖4.24所示。

圖4.24 TimeActivity運行效果
TimeActivity使用的布局文件為time.xml,其內容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/timeview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="DatePicker和TimePicker演示" /> <TimePicker android:id="@+id/timepicker" android:layout_width="wrap_content" android:layout_height="116dp" android:background="#778888" /> <!-- 設置背景色為墨綠 --> <DatePicker android:id="@+id/datepicker" android:layout_width="271dp" android:layout_height="196dp" android:background="#778899" /> </LinearLayout>
TimeActivity.java的代碼如下:
package introduction.android.widgetDemo; import java.util.Calendar; import android.app.Activity;import android.os.Bundle;import android.widget.DatePicker;import android.widget.TextView;import android.widget.TimePicker; public class TimeActivity extends Activity { private TextView textview; private TimePicker timepicker; private DatePicker datepicker; /* 聲明日期及時間變量 */ private int year; private int month; private int day; private int hour; private int minute; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.time); /* 獲取當前日期及時間 */ Calendar calendar=Calendar.getInstance(); year=calendar.get(Calendar.YEAR); month=calendar.get(Calendar.MONTH); day=calendar.get(Calendar.DAY_OF_MONTH); hour=calendar.get(Calendar.HOUR); minute=calendar.get(Calendar.MINUTE); datepicker=(DatePicker)findViewById(R.id.datepicker); timepicker=(TimePicker)findViewById(R.id.timepicker); /* 設置TextView對象,顯示初始日期時間 */ textview=(TextView)findViewById(R.id.timeview); textview.setText(new StringBuilder().append(year).append("/") .append(format(month+1)).append("/").append(format(day)) .append(" ").append(format(hour)).append(":") .append(format(minute))); /* 設置OnDateChangedListener()*/ datepicker.init(year, month, day, new DatePicker.OnDateChangedListener(){ @Override public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth){ // TODO Auto-generated method stub TimeActivity.this.year=year; month=monthOfYear; day=dayOfMonth; textview.setText(new StringBuilder().append(year) .append("/").append(format(month+1)) .append("/").append(format(day)).append(" ") .append(format(hour)).append(":") .append(format(minute))); } }); timepicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() { @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { // TODO Auto-generated method stub hour=hourOfDay; TimeActivity.this.minute=minute; textview.setText(new StringBuilder().append(year) .append("/").append(format(month+1)) .append("/").append(format(day)).append(" ") .append(format(hour)).append(":") .append(format(minute))); } }); } private String format(int time){ String str=""+time;if(str.length()==1) str="0"+str;return str; } }
TimeActivity中使用java.util.Calendar對象獲取當前系統時間。當更改DatePicker組件中的日期時,會觸發DatePicker的OnDateChange()事件;當修改TimePacker的時間時,會觸發TimePacker的OnDateChange()事件。
由本實例可見,DatePicker實現OnDateChangedListener監聽器的方法與TimePicker實現setOnTimeChangedListener監聽器的方法有所類似。DatePicker用init()方法設定年、月、日的同時設定監聽器,而TimePicker使用setOnTimeChangedListener()直接設定。
4.4.10 進度條(ProgressBar)
當應用程序在后臺運行時,可以使用進度條反饋給用戶當前的進度信息。進度條被用以顯示當前應用程序運行狀況,功能完成多少等情況。Android SDK提供兩種樣式的進度條,一種是圓形的進度條,另一種是水平進度條。其中圓形進度條分大、中、小三種。
進度條本質上是一個整數,顯示當前的整數值在特定范圍內的比重。下面用一個簡單的實例講解ProgressBar組件的使用方法。
在工程WidgetDemo的布局文件main.xml中添加一個名為ProgressBarDemo的Button,用以啟動ProcessBarActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ProgressBarDemo" />
單擊Button并啟動ProcessBarActivity的代碼如下:
Button processbtn=(Button)this.findViewById(R.id.button7); processbtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,ProcessBarActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name="ProcessBarActivity"></activity>
ProcessBarActivity運行效果如圖4.25所示。

圖4.25 ProcessBarActivity運行效果
ProcessBarActivity使用的布局文件為processbar.xml,其內容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/progressBar2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/progressBar3" style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ProgressBar android:id="@+id/progressBar4" style="?android:attr/progressBarStyleHorizontal" android:layout_width="209dp" android:layout_height="30dp" android:max="100"/> </LinearLayout>
該布局中放置了小、中、大三種類型的圓形進度條各一個,以及一個水平放置的條形進度條。一般情況下,開發人員不會為圓形進度條指定進度,圓形進度條只是展示運行效果,而不反映實際的進度。水平進度條則不同,開發人員會為條形進度條指定最大值,以及進度條當前值的獲取方法。在本實例中,條形進度條的最大值為100。
ProcessBarActivity.java代碼如下:
package introduction.android.widgetDemo; import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.widget.ProgressBar; public class ProcessBarActivity extends Activity { ProgressBar progressBar; int i=0; int progressBarMax=0; /* 創建Handler對象 */ Handler handler=new Handler(); @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.processbar); progressBar=(ProgressBar)findViewById(R.id.progressBar4); /* 獲取最大值 */ progressBarMax=progressBar.getMax(); /* 匿名內部類啟動實現效果的線程 */ new Thread(new Runnable(){ @Override public void run(){ while(i++<progressBarMax){ // 設置滾動條當前狀態值 progressBar.setProgress(i); try { Thread.sleep(15); } catch(Exception e){ e.printStackTrace(); } } } }).start(); } }
ProcessBarActivity對水平進度條進行了處理。先獲取了水平進度條的最大值,然后啟動了一個線程,由該線程來控制進度條的值,從0開始,每隔15毫秒增加1。
4.4.11 滾動視圖(ScrollView)
當Activity提供的用戶界面上有很多內容,以致當前手機屏幕不能完全顯示全部內容時,就需要滾動視圖來幫助瀏覽全部的內容。
以工程WidgetDemo為例,由于在講述過程中不斷地在main.xml文件中添加按鈕和其他組件,目前已經不能顯示全部內容,效果如圖4.26所示。

圖4.26 添加大量組件后的效果
這時候就需要使用ScrollView,即將當前的Activity的視圖轉化為滾動視圖,以便于瀏覽。ScrollView的使用非常方便,只需在main.xml的<LinearLayout>標簽外面加上ScrollView組件的聲明即可。布局文件main.xml的內容如下:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout>....</LinearLayout> </ScrollView>
添加ScrollView后,main.xml布局的運行效果如圖4.27所示。

圖4.27 ScrollView的運行效果
4.4.12 拖動條(SeekBar)
SeekBar是水平進度條ProgressBar的間接子類,相當于一個可以拖動的水平進度條。下面仍以一個簡單的實例講解SeekBar組件的使用方法。
在工程WidgetDemo的布局文件main.xml中添加一個名為“SeekBarDemo”的Button,用以啟動SeekBarActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="SeekBarDemo" />
單擊Button并啟動SeekBarActivity的代碼如下:
Button processbtn=(Button)this.findViewById(R.id.button8); processbtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this, SeekBarActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name="SeekBarActivity"></activity>
SeekBarActivity運行效果如圖4.28所示。

圖4.28 SeekBarActivity運行效果
SeekBarActivity使用的布局文件為seekbar.xml,其內容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> <SeekBar android:id="@+id/seekBar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100"/> </LinearLayout>
該文件確定SeekBar對象的最大值為100,寬度為手機屏幕的寬度。
SeekBarActivity.java的代碼如下:
package introduction.android.widgetDemo; import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.widget.SeekBar;import android.widget.TextView; public class SeekBarActivity extends Activity { private TextView textView; private SeekBar seekBar; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.seekbar); textView=(TextView)findViewById(R.id.textView1); seekBar=(SeekBar)findViewById(R.id.seekBar1); /* 設置SeekBar監聽setOnSeekBarChangeListener */ seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){ /* 拖動條停止拖動的時調用 */ @Override public void onStopTrackingTouch(SeekBar seekBar){ Log.i("SeekBarActivity", "拖動停止"); } /* 拖動條開始拖動的時調用 */ @Override public void onStartTrackingTouch(SeekBar seekBar){ Log.i("SeekBarActivity", "開始拖動"); } /* 拖動條進度改變的時調用 */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){ /* 拖動條進度改變的時調用 */ textView.setText("當前進度為:"+progress+"%"); } }); } }
SeekBar的事件處理接口為OnSeekBarChangeListener,該監聽器提供對三種事件的監聽,分別為當SeekBar的拖動條開始被拖動時、拖動條拖動停止時和拖動條的位置發生改變時。SeekBarActivity在拖動條開始被拖動和拖動停止時,會通過Logcat打印相關信息。當拖動條位置發生改變時,將當前的數值顯示到TextView中。
4.4.13 評價條(RatingBar)
在網上購物的時候,經常會對所購買商品進行打分的情況。一般對商品的評價和打分是以五顆星的方式進行的。Android SDK提供了RatingBar這個組件來實現該功能。
RatingBar是SeekBar和ProgressBar的擴展,是ProgressBar的間接子類,可以使用ProgressBar相關的屬性。RatingBar有三種風格分別為:默認風格(ratingBarStyle)、小風格(ratingBarStyleSmall)、大風格(ratingBarStyleIndicator)。其中,默認風格的RatingBar是我們通常使用的,可以進行交互,而其他兩種不能進行交互。
以一個簡單的實例講解RatingBar組件的使用方法。在工程WidgetDemo的布局文件main.xml中添加一個名為“RatingBarrDemo”的Button,用以啟動RatingBarActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RatingBarDemo" />
單擊Button并啟動RatingBarActivity的代碼如下:
Button ratingbarbtn=(Button)this.findViewById(R.id.button9); ratingbarbtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,RatingBarActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name="RatingBarActivity"></activity>
RatingBarActivity運行效果如圖4.29所示。

圖4.29 RatingBarActivity運行效果
RatingBarActivity使用的布局文件ratingbar.xml內容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> <RatingBar android:id="@+id/ratingBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numStars="5" android:stepSize="0.5" android:rating="3"/> </LinearLayout>
該布局文件使用LinearLayout布局,其中放置了一個TextView和一個RatingBar,并對RatingBar的相關屬性進行了設置。android:numStars="5"用于設置RatingBar顯示的星星數量為5顆;android:stepSize="0.5"用于設置RatingBar的最小變化單位為半顆星星;android:rating ="3"表示RatingBar在初始狀態下被選中的星星數量為3顆。
RatingBarActivity.java代碼如下:
package introduction.android.widgetDemo; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.RatingBar; import android.widget.RatingBar.OnRatingBarChangeListener; import android.widget.TextView; import android.widget.Toast; public class RatingBarActivity extends Activity { private RatingBar chooseRatingBar; private TextView textView; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.ratingbar); textView=(TextView)findViewById(R.id.textView1); chooseRatingBar=(RatingBar)findViewById(R.id.ratingBar1); /*創建RatingBar監聽器 */ chooseRatingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener(){ @Override public void onRatingChanged(RatingBar ratingBar,float rating, boolean fromUser){ chooseRatingBar=(RatingBar)findViewById(R.id.ratingBar1); chooseRatingBar.setRating(rating); textView.setText("您選擇了"+rating+"個星星"); } }); } }
RatingBarActivity為RatingBar對象設置了OnRatingBarChangeListener監聽器,當用戶單擊RatingBar引起被選中星星數量的變化時,該接口會監測到該事件,并且調用onRatingChanged()方法,更新TextView顯示的內容。
onRatingChanged()的三個參數所對應的含義為:
●ratingBar:多個RatingBar可以同時指定同一個RatingBar監聽器。該參數就是當前觸發RatingBar監聽器的那一個RatingBar對象。
●rating:當前評級分數。取值范圍從0到RatingBar的總星星數。
●fromUser:如果觸發監聽器的是來自用戶觸屏點擊或軌跡球左右移動,則為true。
4.4.14 圖片視圖(ImageView)和圖片按鈕(ImageButton)
ImageView是用于顯示圖片的組件,在很多場合都有比較普遍的使用。ImageView可以顯示任意圖像,加載各種來源的圖片(如資源或圖片庫)。ImageView可以計算圖片的尺寸以便在任意的布局中使用,并且可以提供縮放或者著色等選項供開發者使用。
ImageButton是ImageView的子類,相當于一個表明是圖片而不是文字的Button。其使用方法和Button完全相同。
下面通過一個實例來了解一下這兩個組件的使用方法。在工程WidgetDemo的布局文件main.xml中添加一個名為ImageButtonDemo的Button,用以啟動ImageButtonActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button10" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ImageButtonDemo" />
單擊Button并啟動RatingBarActivity的代碼如下:
Button imgbtn=(Button)this.findViewById(R.id.button10); imgbtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,ImageButtonActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name="ImageButtonActivity"></activity>
ImageButtonActivity運行效果如圖4.30所示。

圖4.30 ImageButtonActivity運行效果
ImageButtonActivity的布局文件imgbtn.xml內容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:id="@+id/imageView1" android:layout_width="250dp" android:layout_height="250dp" android:src="@drawable/girl" /> <ImageButton android:id="@+id/imageButton1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> </LinearLayout>
該文件使用LinearLayout布局,其中放入了一個ImageView組件,一個ImageButton組件。兩個組件都通過android:src屬性指定了顯示的圖片。該實例用到了兩個圖片資源,一個為girl,一個為ic_launcher。由于Android會根據手機設備的配置高低選擇不同的資源,因此為了應用程序的通用性,在三個drawable文件夾下,都放置了girl.gif圖像。ic_launcher.png是系統自帶的資源文件。

圖4.31 工程中的圖片資源
ImageButtonActivity.java代碼如下:
package introduction.android.widgetDemo;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup.LayoutParams;import android.widget.ImageButton;import android.widget.ImageView;public class ImageButtonActivity extends Activity { private ImageButton imgbtn; private ImageView imgview; @Override protected void onCreate(Bundle savedInstanceState){ // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.imgbtn); imgbtn=(ImageButton)this.findViewById(R.id.imageButton1); imgview=(ImageView)this.findViewById(R.id.imageView1); imgbtn.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub LayoutParams params=imgview.getLayoutParams(); params.height+=3; params.width+=3; imgview.setLayoutParams(params); } }); } }
ImageButtonActivity為ImageButton添加了單擊監聽器,對用戶單擊imgbtn的事件進行了處理。每次用戶單擊圖片按鈕,都把ImageView組件的寬和高增大3。隨著用戶的不斷單擊,ImageView中顯示的圖片越來越大,顯示了ImageView組件對圖片的縮放功能。
4.4.15 圖片切換器ImageSwitcher和圖庫Gallery
在使用Android手機設置壁紙的時候,會看到屏幕底部有很多可以滾動的圖片,當單擊某一圖片時,在其上面的空間會顯示當前選中的圖片,此時我們用到的就是Gallery和ImageSwitcher。
Gallery組件用于橫向顯示圖像列表,并且自動將當前圖像放置到中間位置。ImageSwitcher則像是圖片瀏覽器,可以切換圖片,通過它可以制作簡單的幻燈片等等。通常將這兩個類結合在一起使用,可以制作有一定效果的相冊。
下面通過一個實例來了解一下這兩個組件的使用方法。
在工程WidgetDemo的布局文件main.xml中添加一個名為GalleryDemo的Button,用以啟動GalleryActivity。在main.xml中添加代碼如下:
<Button android:id="@+id/button11" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="GalleryDemo" />
單擊Button并啟動GalleryActivity的代碼如下:
Button gallerybtn=(Button)this.findViewById(R.id.button11); gallerybtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,GalleryActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name="GalleryActivity"></activity>
GalleryActivity運行效果如圖4.32所示。

圖4.32 GalleryActivity運行效果
GalleryActivity使用的布局文件為gallery.xml,內容如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <ImageSwitcher android:id="@+id/switcher" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentTop="true" android:layout_alignParentLeft="true"> </ImageSwitcher> <Gallery android:id="@+id/gallery" android:background="#333333" android:layout_width="fill_parent" android:layout_height="60dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:gravity="center_vertical" android:spacing="16dp" /> </RelativeLayout>
該布局文件使用的是相對布局,通過android:layout_alignParentTop="true"這個屬性將ImageSwitcher放置于視圖的頂端,其頂部與其父組件的頂部對齊,同時使用android:layout_alignParentLeft="true"這個屬性使ImageSwitcher的左邊緣與其父組件的左邊緣對齊。在設置Gallery組件時,將其與屏幕的左下角對其,android:layout_alignParentBottom="true"是將該組件的底部與其父組件的底部對齊,并且使用android:spacing="16dp"屬性設置了圖片之間的間距。
GalleryActivity.java代碼如下:
package introduction.android.widgetDemo; import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.view.ViewGroup.LayoutParams;import android.view.animation.AnimationUtils;import android.widget.AdapterView;import android.widget.AdapterView.OnItemSelectedListener;import android.widget.BaseAdapter;import android.widget.Gallery;import android.widget.ImageSwitcher;import android.widget.ImageView;import android.widget.ViewSwitcher.ViewFactory; public class GalleryActivity extends Activity { private Gallery gallery; private ImageSwitcher imageSwitcher; private int[] resids=new int[] { R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7}; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.gallery); /* 加載Gallery和ImageSwitcher */ gallery=(Gallery)findViewById(R.id.gallery); imageSwitcher=(ImageSwitcher)findViewById(R.id.switcher); /* 創建用于描述圖像數據的ImageAdapter對象 */ ImageAdapter imageAdapter=new ImageAdapter(this); /* 設置Gallery組件的Adapter對象 */ gallery.setAdapter(imageAdapter); /* 添加Gallery監聽器 */ gallery.setOnItemSelectedListener(new OnItemSelectedListener(){ @Override public void onItemSelected(AdapterView<?>parent, View view, int position, long id){ // TODO Auto-generated method stub // 當選取Grallery上的圖片時,在ImageSwitcher組件中顯示該圖像 imageSwitcher.setImageResource(resids[position]); } @Override public void onNothingSelected(AdapterView<?>arg0){ // TODO Auto-generated method stub } }); /* 設置ImageSwitcher組件的工廠對象 */ imageSwitcher.setFactory(new ViewFactory(){ /* ImageSwitcher用這個方法來創建一個View對象去顯示圖片 */ @Override public View makeView(){ // TODO Auto-generated method stub ImageView imageView=new ImageView(GalleryActivity.this); /* setScaleType可以設置當圖片大小和容器大小不匹配時的剪輯模式 */ imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); imageView.setLayoutParams(new ImageSwitcher.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); return imageView; } }); /* 設置ImageSwitcher組件顯示圖像的動畫效果 */ imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); } public class ImageAdapter extends BaseAdapter { /* 定義Context */ private Context mContext; /* 聲明ImageAdapter */ public ImageAdapter(Context context){ mContext=context; } @Override /* 獲取圖片的個數 */ public int getCount(){ // TODO Auto-generated method stub return resids.length; } /* 獲取圖片在庫中的位置 */ @Override public Object getItem(int position){ // TODO Auto-generated method stub return position; } /* 獲取圖片ID */ @Override public long getItemId(int position){ // TODO Auto-generated method stub return position; } /* 返回具體位置的ImageView對象 */ @Override public View getView(int position, View convertView, ViewGroup parent){ ImageView imageview=new ImageView(mContext); /* 給ImageView設置資源 */ imageview.setImageResource(resids[position]); /* 設置 圖片布局大小為100*100 */ imageview.setLayoutParams(new Gallery.LayoutParams(100, 100)); /* 設置顯示比例類型 */ imageview.setScaleType(ImageView.ScaleType.FIT_XY); return imageview; } } }
Gallery要顯示的圖片來自資源文件。把需要顯示的圖片放在/res/drawable目錄下后,將這些圖片的ID保存在一個int數組中以備使用。相關代碼如下:
private int[] resids=new int[] { R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7};
Gallery通過setAdapter(imageAdapter)方法將組件和要顯示的圖片關聯起來。本實例中為Gallery設定的適配器為ImageAdapter,主要用于描述圖像信息,其為android.widget. BaseAdapter的子類。
在ImageAdapter類中有兩個方法值得我們注意,其中一個是getCount()方法,它用于返回圖片的總數,通常使用獲取存放圖片數組長度的方法獲取圖片總數,也可以規定具體的返回數,但不能超過實際圖片數量;getView()方法是當Gallery中需要顯示某一個圖像時,將當前圖片的索引,也就是position的值傳入,從resids數組中獲得相應的圖片的ID。
GalleryActivity為添加Gallery監聽器,處理了用戶單擊Gallery中圖片的事件,并設置ImageSwitcher相關屬性。其中代碼如下:
imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
設置了ImageSwitcher組件圖片切換時的漸入和漸出效果。
4.4.16 網格視圖(GridView)
GridView提供了一個二維的可滾動的網格,按照行列的方式來顯示內容,一般適合顯示圖標、圖片等,適合瀏覽。
下面通過一個實例來了解一下GridView組件的使用方法。在工程WidgetDemo的布局文件main.xml中添加一個名為GridViewDemo的Button,用以啟動GridViewActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button12" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="GridViewDemo" />
單擊Button并啟動GridViewActivity的代碼如下:
Button gridviewbtn=(Button)this.findViewById(R.id.button12); gridviewbtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,GridViewActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name="GridViewActivity"></activity>
GridViewActivity運行效果如圖4.33所示。

圖4.33 GridViewActivity運行效果
GridViewActivity使用的布局文件為gridview.xml,其內容如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <GridView android:id="@+id/gridView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:numColumns="3"> </GridView> </LinearLayout>
該視圖采用了LinearLayout的布局方式,其中放置了一個GridView組件,該組件由三列組成。
GridViewActivity.java代碼如下:
package introduction.android.widgetDemo; import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.BaseAdapter;import android.widget.GridView;import android.widget.ImageView; public class GridViewActivity extends Activity { public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.gridview); GridView gridview=(GridView)findViewById(R.id.gridView1); gridview.setAdapter(new ImageAdapter(this)); gridview.setOnItemClickListener(new OnItemClickListener(){ public void onItemClick(AdapterView<?>parent, View v, int position, long id){ Log.i("gridview", "這是第"+position+"幅圖像。"); } }); } public class ImageAdapter extends BaseAdapter { private Context mContext; public ImageAdapter(Context c){ mContext=c; } /* 獲取當前圖片數量 */ @Override public int getCount(){ return mThumbIds.length; } /* 根據需要position獲得在GridView中的對象 */ @Override public Object getItem(int position){ return position; } /* 獲得在GridView中對象的ID */ @Override public long getItemId(int id){ return id; } @Override public View getView(int position, View convertView, ViewGroup parent){ ImageView imageView; if(convertView==null){ /* 實例化ImageView對象 */ imageView=new ImageView(mContext); /* 設置ImageView對象布局 ,設置View的height和width */ imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); /* 設置邊界對齊 */ imageView.setAdjustViewBounds(false); /* 按比例統一縮放圖片(保持圖片的尺寸比例)*/ imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); /* 設置間距 */ imageView.setPadding(8, 8, 8, 8); } else { imageView=(ImageView)convertView; } imageView.setImageResource(mThumbIds[position]); return imageView; } } // references to our images private Integer[] mThumbIds={ R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7 }; }
在主程序GridViewActivity中,為GridView設置了一個數據適配器,并處理了GridView的單擊事件。適配器繼承自BaseAdapter類,與上章節中用到的適配器高度相似,在此不再重復。
4.4.17 標簽(Tab)
在有限的手機屏幕空間內,當要瀏覽的內容較多,無法在一個屏幕空間內全部顯示時,可以使用滾動視圖來延長屏幕的空間。當瀏覽的內容具有很強的類別性質時,更合適的方法是將不同類別的內容集中到各自的面板中,這時就需要使用面板Tab組件了。
Tab組件利用面板標簽把不同的面板內容切換到屏幕上,以顯示不同類別的內容。
下面通過一個實例來了解一下Tab組件的使用方法。在工程WidgetDemo的布局文件main.xml中添加一個名為TabDemo的Button,用以啟動TabActivity。
在main.xml中添加代碼如下:
<Button android:id="@+id/button13" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TabDemo" />
單擊Button并啟動GridViewActivity的代碼如下:
Button tabbtn=(Button)this.findViewById(R.id.button13); tabbtn.setOnClickListener(new OnClickListener(){ @Overridepublic void onClick(View v){ // TODO Auto-generated method stub Intent intent=new Intent(WidgetDemoActivity.this,TabActivity.class); startActivity(intent); } });
同時在AndroidManifest.xml文件中聲明該Activity:
<activity android:name="TabActivity"></activity>
TabActivity運行效果如圖4.34所示。

圖4.34 TabActivity運行效果
要使用Tab必然涉及它的容器TabHost,TabHost包括TabWigget和FrameLayout兩部分。TabWidget就是每個Tab的標簽,FrameLayout是Tab的內容。
TabActivity使用的布局文件是tab.xml。在tab.xml中定義了每個Tab中要顯示的內容,代碼如下:
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/tab1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="40dp" android:text="Tab1頁面" /> <TextView android:id="@+id/tab2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="40dp" android:text="Tab2頁面" /> <TextView android:id="@+id/tab3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="40dp" android:text="Tab3頁面" /> </FrameLayout> </LinearLayout> </TabHost>
在FrameLayout中我們放置了三個TextView組件,分別對應三個Tab所顯示的內容,當切換不同的Tab時會自動顯示不同的TextView內容。
在主程序TabActivity的OnCreate()方法中,首先獲得了TabHost的對象,并調用setup()方法進行初始化,然后通過TabHost.TabSpec增加Tab頁,通過setContent()增加當前Tab頁顯示的內容,通過setIndicator增加頁的標簽,最后設定當前要顯示的Tab頁。
TabActivity代碼如下:
package introduction.android.widgetDemo; import android.app.Activity; import android.os.Bundle; import android.widget.TabHost; public class TabsActivity extends Activity { public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.tab); // 步驟1:獲得TabHost的對象,并進行初始化setup() TabHost tabs=(TabHost)findViewById(R.id.tabhost); tabs.setup(); // 步驟2:通過TabHost.TabSpec增加tab的一頁,通過setContent()增加內容,通過setIndicator增加頁的標簽 /* 增加第1個Tab */ TabHost.TabSpec spec=tabs.newTabSpec("Tag1"); // 單擊Tab要顯示的內容 spec.setContent(R.id.tab1); /* 顯示Tab3內容 */ spec.setIndicator("Tab1"); tabs.addTab(spec); /* 增加第2個Tab */ spec=tabs.newTabSpec("Tag2"); spec.setContent(R.id.tab2);// 單擊Tab要顯示的內容 /* 顯示Tab3內容 */ spec.setIndicator("Tab2"); tabs.addTab(spec); /* 增加第3個Tab */ spec=tabs.newTabSpec("Tag3"); spec.setContent(R.id.tab3);// 單擊Tab要顯示的內容 /* 顯示Tab3內容 */ spec.setIndicator("Tab3"); tabs.addTab(spec); /* 步驟3:可通過setCurrentTab(index)指定顯示的頁,從0開始計算。 */ tabs.setCurrentTab(0); } }
除了使用上述方法設置Tab頁面的顯示內容外,還可以使用setContent(Intent)方法啟動某個Activity,并將該Activity的視圖作為Tab頁面的內容。
例如:
Intent intent=new Intent().setClass(this, AlbumsActivity.class); spec=tabHost.newTabSpec("albums").setIndicator("Albums", res.getDrawable(R.drawable.ic_tab_albums)) .setContent(intent); tabHost.addTab(spec);
- 少兒人工智能趣味入門:Scratch 3.0動畫與游戲編程
- JavaScript高效圖形編程
- Visual C++串口通信開發入門與編程實踐
- Azure IoT Development Cookbook
- Pandas Cookbook
- 深入淺出Prometheus:原理、應用、源碼與拓展詳解
- Python程序設計
- Unity 5 for Android Essentials
- Creating Mobile Apps with jQuery Mobile(Second Edition)
- Spring Boot+MVC實戰指南
- Python函數式編程(第2版)
- 算法設計與分析:基于C++編程語言的描述
- Java Web應用開發
- Java核心技術速學版(第3版)
- C#程序設計基礎與實踐