6.顯示一個使用者對話方塊
6.1 問題
需要向用戶顯示一個簡單的彈出式對話方塊來進行事件通知或展示一個選項列表。
6.2 解決方案
(API Level 1)
在向用戶快速展示重要模態資訊的場景中,AlertDialog是最高效的解決方案。它展示的內容可以很輕鬆地進行自定義,同時框架還提供一個方便的AlertDialog.Builder類來快速構建彈出式對話方塊。
6.3 實現機制
通過使用AlertDialog.Builder,可以構建類似的報警對話方塊,但包含不同的額外選項。AlertDialog在建立簡單的彈出式對話方塊來獲得使用者反饋時是一個非常有用的類。通過AlertDialog.Builder,可以很容易在一個簡潔的小部件中新增單選或多選列表、按鈕和訊息字串。
為了說明這一點,讓我們用AlertDialog建立一個和以前一樣的彈出式選擇框。這一次,我們將在選項列表的底增加Cancel按鈕(參見以下程式碼)。
使用了AlertDialog的動作選單
public class DialogActivity extends Activity implements DialogInterface.OnClickListener, View.OnClickListener { private static final String[] ZONES = {"Pacific Time", "Mountain Time", "Central Time", "Eastern Time", "Atlantic Time"}; Button mButton; AlertDialog mActions; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mButton = new Button(this); mButton.setText("Click for Time Zones"); mButton.setOnClickListener(this); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Select Time Zone"); builder.setItems(ZONES, this); //這裡的取消動作只會讓對話方塊消失,但在使用者單擊Cancel按鈕時, // 也可以新增另一個監聽器來處理一些其他的操作 builder.setNegativeButton("Cancel", null); mActions = builder.create(); setContentView(mButton); } //這裡處理列表的選擇事件 @Override public void onClick(DialogInterface dialog, int which) { String selected = ZONES[which]; mButton.setText(selected); } //這裡處理按鈕的單擊事件 (彈出對話方塊) @Override public void onClick(View v) { mActions.show(); } }
本例中,我們建立了一個新的AlertDialog.Builder例項並使用它的便捷方法添加了如下條目:
- 標題 : 通過setTitle()設定。
- 選項列表,通過setItems()和一個字串陣列(也可以是陣列資源)設定。
- Cancel按鈕,通過setNegativeButton()設定。
當選擇列表中的一個選項時,我們關聯到列表項的監聽器會返回所選擇的選項(索引是之前提供的陣列的索引,從0開始),然後我們就可以根據使用者的選擇來更新按鈕上的文字資訊。對於Cancel按鈕,因為我們只想在按下Cancel按鈕時關閉對話方塊,所以我們為Cancel按鈕傳入的監聽器為null。如果在按下Cancel按鈕時還想處理一些重要的工作,可以向setNegativeButton()方法傳入其他的監聽器。
另外,還要其他的一些選項可以設定除了選項列表之外的對話方塊中的內容:
- setMessage()可以為對話方塊的內容設定除了選項列表之外的對話方塊中的內容。
- setSingleChoiceItems()和setMultiChoiceItems()會建立一個與本例類似的列表,但每個選項是以複選框的方式顯示的。
- setView()可以為對話方塊的內容使用任意自定義檢視。

帶有選項列表的AlertDialog
自定義列表條目
AlertDialog.Builder允許傳入一個自定義的ListAdapter作為對話方塊中顯示列表條目的資料來源,這也意味著我們可以自定義列表中的每一行的佈局來向用戶顯示更加詳細的資訊。在以下兩個程式碼中改進了之前的示例,為每一行使用自定義的行佈局來顯示每個條目的其他資訊。
res/layout.list_item.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="10dp" android:paddingRight="10dp" android:minHeight="?android:attr/listPreferredItemHeight"> <TextView android:id="@+id/text_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:textAppearance="?android:attr/textAppearanceMedium"/> <TextView android:id="@+id/text_detail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:textAppearance="?android:attr/textAppearanceSmall"/> </RelativeLayout>
帶有自定義佈局的AlertDialog
public class CustomItemActivity extends Activity implements DialogInterface.OnClickListener, View.OnClickListener { private static final String[] ZONES = {"Pacific Time", "Mountain Time", "Central Time", "Eastern Time", "Atlantic Time"}; private static final String[] OFFSETS = {"GMT-08:00", "GMT-07:00", "GMT-06:00", "GMT-05:00", "GMT-04:00"}; Button mButton; AlertDialog mActions; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mButton = new Button(this); mButton.setText("Click for Time Zones"); mButton.setOnClickListener(this); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item) { @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) { row = getLayoutInflater().inflate(R.layout.list_item, parent, false); } TextView name = (TextView) row.findViewById(R.id.text_name); TextView detail = (TextView) row.findViewById(R.id.text_detail); name.setText(ZONES[position]); detail.setText(OFFSETS[position]); return row; } @Override public int getCount() { return ZONES.length; } }; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Select Time Zone"); builder.setAdapter(adapter, this); //這裡的取消動作只會讓對話方塊消失,但在使用者單擊Cancel按鈕時, //也可以新增一個監聽器來處理一些其他的操作 builder.setNegativeButton("Cancel", null); mActions = builder.create(); setContentView(mButton); } //這裡處理列表的選擇事件 @Override public void onClick(DialogInterface dialog, int which) { String selected = ZONES[which]; mButton.setText(selected); } //這裡處理按鈕的單擊事件 (彈出對話方塊) @Override public void onClick(View v) { mActions.show(); } }
這裡我們為生成器提供了一個ArrayAdapter,而不是簡單地傳入了選項陣列。ArrayAdapter有getView()的自定義實現,會返回一個XML中自定義佈局,我們現在可以顯示GMT偏移值和時區名稱。之後會進一步討論自定義介面卡的特性。如圖顯示了新的、更加實用的彈出式對話方塊。

帶有自定義條目的AlertDialog