| page.title=對話方塊 |
| page.tags=alertdialog,dialogfragment |
| |
| @jd:body |
| |
| |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>本文件內容</h2> |
| <ol> |
| <li><a href="#DialogFragment">建立對話方塊片段</a></li> |
| <li><a href="#AlertDialog">建置快訊對話方塊</a> |
| <ol> |
| <li><a href="#AddingButtons">加入按鈕</a></li> |
| <li><a href="#AddingAList">加入清單</a></li> |
| <li><a href="#CustomLayout">建立自訂版面配置</a></li> |
| </ol> |
| </li> |
| <li><a href="#PassingEvents">將事件傳回對話方塊的主控件</a></li> |
| <li><a href="#ShowingADialog">顯示對話方塊</a></li> |
| <li><a href="#FullscreenDialog">顯示全螢幕對話方塊或內嵌片段</a> |
| <ol> |
| <li><a href="#ActivityAsDialog">針對大型螢幕將 Activity 顯示為對話方塊</a></li> |
| </ol> |
| </li> |
| <li><a href="#DismissingADialog">關閉對話方塊</a></li> |
| </ol> |
| |
| <h2>重要類別</h2> |
| <ol> |
| <li>{@link android.app.DialogFragment}</li> |
| <li>{@link android.app.AlertDialog}</li> |
| </ol> |
| |
| <h2>另請參閱</h2> |
| <ol> |
| <li><a href="{@docRoot}design/building-blocks/dialogs.html">對話方塊設計指南</a></li> |
| <li><a href="{@docRoot}guide/topics/ui/controls/pickers.html">挑選器</a> (日期/時間對話方塊)</li> |
| </ol> |
| </div> |
| </div> |
| |
| <p>對話方塊是一種小型視窗,可提示使用者做出決定或輸入額外資訊。 |
| 對話視窗並不會佔滿整個螢幕,而且通常是供強制回應事件使用,這種事件會要求使用者必須先完成特定動作,才能繼續下一步。 |
| </p> |
| |
| <div class="note design"> |
| <p><strong>設計對話方塊</strong></p> |
| <p>如要瞭解如何設計對話方塊,包括建議使用的設計語言,請參閱<a href="{@docRoot}design/building-blocks/dialogs.html">對話方塊</a>設計指南。 |
| </p> |
| </div> |
| |
| <img src="{@docRoot}images/ui/dialogs.png" /> |
| |
| <p>{@link android.app.Dialog} 類別是對話方塊的基礎類別,但請避免直接啟動 {@link android.app.Dialog}。建議您改用下列其中一個子類別: |
| |
| </p> |
| <dl> |
| <dt>{@link android.app.AlertDialog}</dt> |
| <dd>這種對話方塊可以顯示一個標題、最多三個按鈕、一系列可選取項目或一個自訂版面配置。 |
| </dd> |
| <dt>{@link android.app.DatePickerDialog} 或 {@link android.app.TimePickerDialog}</dt> |
| <dd>這種對話方塊會提供預先定義的 UI,可讓使用者選取日期或時間。</dd> |
| </dl> |
| |
| <div class="sidebox"> |
| <h2>避免使用 ProgressDialog</h2> |
| <p>Android 包含另一個稱為 |
| {@link android.app.ProgressDialog} 的對話方塊類別,可顯示內含進度列的對話方塊。不過,如果您需要向使用者指明載入進度或不明朗的進度,建議您按照<a href="{@docRoot}design/building-blocks/progress.html">進度和 Activity</a> 設計指導方針中的指示操作,並且在版面配置中使用 {@link android.widget.ProgressBar}。 |
| |
| |
| </p> |
| </div> |
| |
| <p>上述類別可定義對話方塊的樣式和結構,但建議您使用 {@link android.support.v4.app.DialogFragment} 做為對話方塊的容器。 |
| {@link android.support.v4.app.DialogFragment} 類別可提供您所需的所有控制項,方便您建立對話方塊及管理對話方塊的外觀,如此您不必對 {@link android.app.Dialog} 物件呼叫方法。 |
| |
| |
| </p> |
| |
| <p>使用 {@link android.support.v4.app.DialogFragment} 管理對話方塊可確保對話方塊能正確控制生命週期事件,例如使用者點擊 [返回]<em></em> 按鈕或旋轉螢幕。 |
| |
| 此外,{@link |
| android.support.v4.app.DialogFragment} 類別還能像傳統的 {@link |
| android.support.v4.app.Fragment} 一樣讓您重複使用對話方塊的 UI,做為大型 UI 中的可嵌入元件 (例如當您想讓對話方塊使用者介面在大型和小型螢幕上呈現不同外觀時)。 |
| |
| </p> |
| |
| <p>本指南的以下各節說明如何搭配 {@link android.app.AlertDialog} 物件使用 {@link |
| android.support.v4.app.DialogFragment}。 |
| 如果您是想建立日期或時間挑選器,請改為參閱<a href="{@docRoot}guide/topics/ui/controls/pickers.html">挑選器</a>指南。 |
| </p> |
| |
| <p class="note"><strong>注意:</strong>{@link android.app.DialogFragment} 類別最初是在 Android 3.0 (API 級別 11) 中導入,因此本文說明如何使用<a href="{@docRoot}tools/support-library/index.html">支援程式庫</a>提供的 {@link |
| android.support.v4.app.DialogFragment} 類別。 |
| |
| 只要將這個程式庫加到您的應用程式,即可在搭載 Android 1.6 以上版本的裝置上使用 {@link android.support.v4.app.DialogFragment} 以及多種其他 API。 |
| |
| 如果您應用程式支援的最低版本為 API 級別 11 以上版本,您就可以使用架構版本的 {@link |
| android.app.DialogFragment},但請注意,本文中提供的連結是用於取得支援程式庫 API。 |
| |
| 使用支援程式庫時,請務必匯入 <code>android.support.v4.app.DialogFragment</code> 類別,而「不是」<em></em><code>android.app.DialogFragment</code>。 |
| |
| </p> |
| |
| |
| <h2 id="DialogFragment">建立對話方塊片段</h2> |
| |
| <p>如果想建立多種對話方塊設計 — 包括自訂版面配置和<a href="{@docRoot}design/building-blocks/dialogs.html">對話方塊</a>設計指南中所述的對話方塊設計 — 只要延伸 |
| {@link android.support.v4.app.DialogFragment} 然後利用 |
| {@link android.support.v4.app.DialogFragment#onCreateDialog |
| onCreateDialog()} 回呼方法建立 {@link android.app.AlertDialog} 即可。 |
| |
| </p> |
| |
| <p>例如,假設您利用 {@link android.support.v4.app.DialogFragment} 管理以下的基本 |
| {@link android.app.AlertDialog}:</p> |
| |
| <pre> |
| public class FireMissilesDialogFragment extends DialogFragment { |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| // Use the Builder class for convenient dialog construction |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| builder.setMessage(R.string.dialog_fire_missiles) |
| .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int id) { |
| // FIRE ZE MISSILES! |
| } |
| }) |
| .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int id) { |
| // User cancelled the dialog |
| } |
| }); |
| // Create the AlertDialog object and return it |
| return builder.create(); |
| } |
| } |
| </pre> |
| |
| <div class="figure" style="width:290px;margin:0 0 0 20px"> |
| <img src="{@docRoot}images/ui/dialog_buttons.png" alt="" /> |
| <p class="img-caption"><strong>圖 1.</strong> |
| 包含一段訊息和兩個動作按鈕的對話方塊。</p> |
| </div> |
| |
| <p>在這種情況下,如果您建立這個類別執行個體,然後對該物件呼叫 {@link |
| android.support.v4.app.DialogFragment#show show()},就會顯示如圖 1 所示的對話方塊。 |
| </p> |
| |
| <p>如要進一步瞭解如何使用 {@link android.app.AlertDialog.Builder} API 建立對話方塊,請參閱下一節。 |
| </p> |
| |
| <p>視對話方塊的複雜程度而定,您可以在 {@link android.support.v4.app.DialogFragment} 中實作多種其他回呼方法,包括所有的基本<a href="{@docRoot}guide/components/fragments.html#Lifecycle">片段生命週期方法</a>。 |
| |
| |
| |
| |
| |
| |
| |
| <h2 id="AlertDialog">建置快訊對話方塊</h2> |
| |
| |
| <p>{@link android.app.AlertDialog} 通常是您需要使用的唯一對話方塊類別,可讓您建置多種對話方塊設計。如圖 2 所示,快訊對話方塊是由 3 個區塊組合而成: |
| |
| </p> |
| |
| <div class="figure" style="width:311px;margin-top:0"> |
| <img src="{@docRoot}images/ui/dialogs_regions.png" alt="" style="margin-bottom:0" /> |
| <p class="img-caption"><strong>圖 2.</strong>對話方塊的版面配置。</p> |
| </div> |
| |
| <ol> |
| <li><b>標題</b> |
| <p>此為選用區塊;只有在內容區域提供詳細訊息、一份清單或自訂版面配置時,您才需要使用標題。 |
| 如果您想提供一段簡短訊息或一個簡易問題 (如圖 1 所示的對話方塊),您就不必使用標題。 |
| </li> |
| <li><b>內容區塊</b> |
| <p>這個區塊可以顯示一段訊息、一份清單或其他自訂版面配置。</p></li> |
| <li><b>動作按鈕</b> |
| <p>單一對話方塊最多只能包含 3 個動作按鈕。</p></li> |
| </ol> |
| |
| <p>{@link android.app.AlertDialog.Builder} 類別提供的 API 可讓您建立包含這些內容類型 (包括自訂版面配置) 的 {@link android.app.AlertDialog}。 |
| |
| </p> |
| |
| <p>如何建置 {@link android.app.AlertDialog}:</p> |
| |
| <pre> |
| <b>// 1. Instantiate an {@link android.app.AlertDialog.Builder} with its constructor</b> |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| |
| <b>// 2. Chain together various setter methods to set the dialog characteristics</b> |
| builder.setMessage(R.string.dialog_message) |
| .setTitle(R.string.dialog_title); |
| |
| <b>// 3. Get the {@link android.app.AlertDialog} from {@link android.app.AlertDialog.Builder#create()}</b> |
| AlertDialog dialog = builder.create(); |
| </pre> |
| |
| <p>以下主題說明如何定義多種採用 {@link android.app.AlertDialog.Builder} 類別的對話方塊屬性。 |
| </p> |
| |
| |
| |
| |
| <h3 id="AddingButtons">加入按鈕</h3> |
| |
| <p>想要加入如圖 2 所示的動作按鈕,請呼叫 {@link android.app.AlertDialog.Builder#setPositiveButton setPositiveButton()} 和 |
| {@link android.app.AlertDialog.Builder#setNegativeButton setNegativeButton()} 方法: |
| </p> |
| |
| <pre style="clear:right"> |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| // Add the buttons |
| builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int id) { |
| // User clicked OK button |
| } |
| }); |
| builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int id) { |
| // User cancelled the dialog |
| } |
| }); |
| // Set other dialog properties |
| ... |
| |
| // Create the AlertDialog |
| AlertDialog dialog = builder.create(); |
| </pre> |
| |
| <p><code>set...Button()</code> 方法會要求<a href="{@docRoot}guide/topics/resources/string-resource.html">字串資源</a>提供的按鈕標題,以及可定義使用者點擊按鈕後需要完成的動作的{@link android.content.DialogInterface.OnClickListener}。 |
| |
| |
| </p> |
| |
| <p>您可以加入的動作按鈕分為 3 種:</p> |
| <dl> |
| <dt>正面</dt> |
| <dd>這種按鈕的用途是接受及繼續進行特定動作 (「確定」按鈕)。</dd> |
| <dt>負面</dt> |
| <dd>這種按鈕的用途是取消動作。</dd> |
| <dt>中立</dt> |
| <dd>如果使用者不想繼續進行特定動作,但並非要取消動作,請使用這種按鈕。 |
| 這種按鈕會顯示在正面和負面按鈕之間。 |
| 範例:[稍後提醒我] 按鈕。</dd> |
| </dl> |
| |
| <p>您可以將以上其中一種按鈕加入 {@link |
| android.app.AlertDialog};換句話說,您最多只能加入一個「正面」按鈕。</p> |
| |
| |
| |
| <div class="figure" style="width:290px;margin:0 0 0 40px"> |
| <img src="{@docRoot}images/ui/dialog_list.png" alt="" /> |
| <p class="img-caption"><strong>圖 3.</strong> |
| 包含一個標題和一份清單的對話方塊。</p> |
| </div> |
| |
| <h3 id="AddingAList">加入清單</h3> |
| |
| <p>{@link android.app.AlertDialog} API 可提供以下 3 種清單類型:</p> |
| <ul> |
| <li>傳統的單一選項清單</li> |
| <li>永續性的單一選項清單 (圓形按鈕)</li> |
| <li>永續性的多重選項清單 (核取方塊)</li> |
| </ul> |
| |
| <p>想要建立如圖 3 所示的單一選項清單,請使用 {@link android.app.AlertDialog.Builder#setItems setItems()} 方法: |
| </p> |
| |
| <pre style="clear:right"> |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| builder.setTitle(R.string.pick_color) |
| .setItems(R.array.colors_array, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int which) { |
| // The 'which' argument contains the index position |
| // of the selected item |
| } |
| }); |
| return builder.create(); |
| } |
| </pre> |
| |
| <p>由於清單會出現在對話方塊的內容區塊中,因此對話方塊無法同時顯示訊息和清單,而且您必須使用 {@link android.app.AlertDialog.Builder#setTitle setTitle()} 為對話方塊設定標題。 |
| |
| 如要指定清單列出的項目,請呼叫 {@link |
| android.app.AlertDialog.Builder#setItems setItems()} 來傳送陣列。或者,您也可以使用 {@link |
| android.app.AlertDialog.Builder#setAdapter setAdapter()} 指定清單。 |
| |
| 如此一來,您就可以使用 {@link android.widget.ListAdapter} 為清單加入動態資料 (例如資料庫中的動態資料)。 |
| </p> |
| |
| <p>如果您選擇讓清單採用 {@link android.widget.ListAdapter},請一律使用 {@link android.support.v4.content.Loader} 以非同步方式載入內容。 |
| |
| 詳情請參閱<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">使用配接器建置版面配置</a>和<a href="{@docRoot}guide/components/loaders.html">載入器</a>指南。 |
| |
| |
| </p> |
| |
| <p class="note"><strong>注意:</strong>在預設情況下,輕觸某個清單項目會關閉對話方塊,除非您使用以下的永續性選項清單。 |
| </p> |
| |
| <div class="figure" style="width:290px;margin:-30px 0 0 40px"> |
| <img src="{@docRoot}images/ui/dialog_checkboxes.png" /> |
| <p class="img-caption"><strong>圖 4.</strong> |
| 多重選項清單。</p> |
| </div> |
| |
| |
| <h4 id="Checkboxes">加入永續性的多重選項或單一選項清單</h4> |
| |
| <p>如要加入多重選項 (核取方塊) 或單一選項 (圓形按鈕),請使用 |
| {@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String, |
| DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} 或 |
| {@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) |
| setSingleChoiceItems()} 方法。 |
| </p> |
| |
| <p>例如,以下說明如何建立如圖 4 所示能夠在 {@link java.util.ArrayList} 中儲存所選項目的多重選項清單: |
| |
| </p> |
| |
| <pre style="clear:right"> |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| mSelectedItems = new ArrayList(); // Where we track the selected items |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| // Set the dialog title |
| builder.setTitle(R.string.pick_toppings) |
| // Specify the list array, the items to be selected by default (null for none), |
| // and the listener through which to receive callbacks when items are selected |
| .setMultiChoiceItems(R.array.toppings, null, |
| new DialogInterface.OnMultiChoiceClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int which, |
| boolean isChecked) { |
| if (isChecked) { |
| // If the user checked the item, add it to the selected items |
| mSelectedItems.add(which); |
| } else if (mSelectedItems.contains(which)) { |
| // Else, if the item is already in the array, remove it |
| mSelectedItems.remove(Integer.valueOf(which)); |
| } |
| } |
| }) |
| // Set the action buttons |
| .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int id) { |
| // User clicked OK, so save the mSelectedItems results somewhere |
| // or return them to the component that opened the dialog |
| ... |
| } |
| }) |
| .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int id) { |
| ... |
| } |
| }); |
| |
| return builder.create(); |
| } |
| </pre> |
| |
| <p>雖然傳統清單和包含圓形按鈕的清單都可提供「單選」動作,但如果您想保留使用者的選擇,請使用 {@link |
| android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) |
| setSingleChoiceItems()}。也就是說,如果您想讓對話方塊再次開啟時顯示使用者目前所選的選項,請建立包含圓形按鈕的清單。 |
| |
| |
| </p> |
| |
| |
| |
| |
| |
| <h3 id="CustomLayout">建立自訂版面配置</h3> |
| |
| <div class="figure" style="width:290px;margin:-30px 0 0 40px"> |
| <img src="{@docRoot}images/ui/dialog_custom.png" alt="" /> |
| <p class="img-caption"><strong>圖 5.</strong>自訂的對話方塊版面配置。</p> |
| </div> |
| |
| <p>如果您想自訂對話方塊的版面配置,請建立所需的版面配置,然後對 {@link |
| android.app.AlertDialog.Builder} 物件呼叫 {@link |
| android.app.AlertDialog.Builder#setView setView()},將新建的版面配置加到 {@link android.app.AlertDialog}。 |
| </p> |
| |
| <p>自訂版面配置預設會佔滿整個對話方塊視窗,但您仍可使用 {@link android.app.AlertDialog.Builder} 方法在其中加入按鈕和標題。 |
| </p> |
| |
| <p>例如,以下是圖 5 所示的對話方塊版面配置檔案:</p> |
| |
| <p style="clear:right" class="code-caption">res/layout/dialog_signin.xml</p> |
| <pre> |
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| android:orientation="vertical" |
| android:layout_width="wrap_content" |
| android:layout_height="wrap_content"> |
| <ImageView |
| android:src="@drawable/header_logo" |
| android:layout_width="match_parent" |
| android:layout_height="64dp" |
| android:scaleType="center" |
| android:background="#FFFFBB33" |
| android:contentDescription="@string/app_name" /> |
| <EditText |
| android:id="@+id/username" |
| android:inputType="textEmailAddress" |
| android:layout_width="match_parent" |
| android:layout_height="wrap_content" |
| android:layout_marginTop="16dp" |
| android:layout_marginLeft="4dp" |
| android:layout_marginRight="4dp" |
| android:layout_marginBottom="4dp" |
| android:hint="@string/username" /> |
| <EditText |
| android:id="@+id/password" |
| android:inputType="textPassword" |
| android:layout_width="match_parent" |
| android:layout_height="wrap_content" |
| android:layout_marginTop="4dp" |
| android:layout_marginLeft="4dp" |
| android:layout_marginRight="4dp" |
| android:layout_marginBottom="16dp" |
| android:fontFamily="sans-serif" |
| android:hint="@string/password"/> |
| </LinearLayout> |
| </pre> |
| |
| <p class="note"><strong>提示:</strong>在預設情況下,如果您設定 {@link android.widget.EditText} 元素使用 {@code "textPassword"} 輸入類型,字型系列就會設為等寬字型,因此您必須將該元素的字型系列變更為 {@code "sans-serif"},讓文字欄位採用對應的字型。 |
| |
| |
| </p> |
| |
| <p>如要擴大 {@link android.support.v4.app.DialogFragment} 中的版面配置,請透過 {@link android.app.Activity#getLayoutInflater()} 取得 {@link android.view.LayoutInflater},然後呼叫{@link android.view.LayoutInflater#inflate inflate()} (其中的第一個參數為版面配置資源 ID,第二個參數則是版面配置的上層檢視)。接著,您可以呼叫 {@link android.app.AlertDialog#setView setView()} 來取代對話方塊中的版面配置。 |
| |
| |
| |
| |
| |
| </p> |
| |
| <pre> |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| // Get the layout inflater |
| LayoutInflater inflater = getActivity().getLayoutInflater(); |
| |
| // Inflate and set the layout for the dialog |
| // Pass null as the parent view because its going in the dialog layout |
| builder.setView(inflater.inflate(R.layout.dialog_signin, null)) |
| // Add action buttons |
| .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() { |
| @Override |
| public void onClick(DialogInterface dialog, int id) { |
| // sign in the user ... |
| } |
| }) |
| .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int id) { |
| LoginDialogFragment.this.getDialog().cancel(); |
| } |
| }); |
| return builder.create(); |
| } |
| </pre> |
| |
| <div class="note"> |
| <p><strong>提示:</strong>如果您想自訂對話方塊,請改為將 {@link android.app.Activity} 顯示為對話方塊,而不是使用 {@link android.app.Dialog} API。 |
| |
| 方法很簡單,只要建立 Activity 然後在 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code |
| <activity>}</a> 宣示說明元素中將其主題設為 |
| {@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog} 即可: |
| </p> |
| |
| <pre> |
| <activity android:theme="@android:style/Theme.Holo.Dialog" > |
| </pre> |
| <p>這樣一來,Activity 就會顯示在對話方塊視窗,而不是以全螢幕模式顯示。</p> |
| </div> |
| |
| |
| |
| <h2 id="PassingEvents">將事件傳回對話方塊的主控件</h2> |
| |
| <p>使用者在對話方塊中輕觸任一動作按鈕或從清單中選取一個項目後,您的 {@link android.support.v4.app.DialogFragment} 可能會自行執行必要動作,不過,您通常會想將事件傳送到 Activity 或對話方塊開啟的片段。 |
| |
| |
| 如要這麼做,請透過每個點擊事件類型適用的方法定義介面,然後在會接收對話方塊的動作事件的主機元件中實作該介面。 |
| |
| </p> |
| |
| <p>例如,以下是定義用於將事件傳回主機 Activity 的介面的 {@link android.support.v4.app.DialogFragment}: |
| </p> |
| |
| <pre> |
| public class NoticeDialogFragment extends DialogFragment { |
| |
| /* The activity that creates an instance of this dialog fragment must |
| * implement this interface in order to receive event callbacks. |
| * Each method passes the DialogFragment in case the host needs to query it. */ |
| public interface NoticeDialogListener { |
| public void onDialogPositiveClick(DialogFragment dialog); |
| public void onDialogNegativeClick(DialogFragment dialog); |
| } |
| |
| // Use this instance of the interface to deliver action events |
| NoticeDialogListener mListener; |
| |
| // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener |
| @Override |
| public void onAttach(Activity activity) { |
| super.onAttach(activity); |
| // Verify that the host activity implements the callback interface |
| try { |
| // Instantiate the NoticeDialogListener so we can send events to the host |
| mListener = (NoticeDialogListener) activity; |
| } catch (ClassCastException e) { |
| // The activity doesn't implement the interface, throw exception |
| throw new ClassCastException(activity.toString() |
| + " must implement NoticeDialogListener"); |
| } |
| } |
| ... |
| } |
| </pre> |
| |
| <p>代管對話方塊的 Activity 會建立包含對話方塊片段的建構函式的對話方塊執行個體,以及透過您實作的 {@code NoticeDialogListener} 介面接收對話方塊的事件: |
| |
| </p> |
| |
| <pre> |
| public class MainActivity extends FragmentActivity |
| implements NoticeDialogFragment.NoticeDialogListener{ |
| ... |
| |
| public void showNoticeDialog() { |
| // Create an instance of the dialog fragment and show it |
| DialogFragment dialog = new NoticeDialogFragment(); |
| dialog.show(getSupportFragmentManager(), "NoticeDialogFragment"); |
| } |
| |
| // The dialog fragment receives a reference to this Activity through the |
| // Fragment.onAttach() callback, which it uses to call the following methods |
| // defined by the NoticeDialogFragment.NoticeDialogListener interface |
| @Override |
| public void onDialogPositiveClick(DialogFragment dialog) { |
| // User touched the dialog's positive button |
| ... |
| } |
| |
| @Override |
| public void onDialogNegativeClick(DialogFragment dialog) { |
| // User touched the dialog's negative button |
| ... |
| } |
| } |
| </pre> |
| |
| <p>由於主機 Activity 會實作 {@code NoticeDialogListener} — 如上所述的 {@link android.support.v4.app.Fragment#onAttach onAttach()} 回呼方法會強制執行這個 Activity — 因此對話方塊片段可以使用介面回呼方法將點擊事件傳送到 Activity: |
| |
| |
| </p> |
| |
| <pre> |
| public class NoticeDialogFragment extends DialogFragment { |
| ... |
| |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| // Build the dialog and set up the button click handlers |
| AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); |
| builder.setMessage(R.string.dialog_fire_missiles) |
| .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int id) { |
| // Send the positive button event back to the host activity |
| mListener.onDialogPositiveClick(NoticeDialogFragment.this); |
| } |
| }) |
| .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int id) { |
| // Send the negative button event back to the host activity |
| mListener.onDialogNegativeClick(NoticeDialogFragment.this); |
| } |
| }); |
| return builder.create(); |
| } |
| } |
| </pre> |
| |
| |
| |
| <h2 id="ShowingADialog">顯示對話方塊</h2> |
| |
| <p>如果想顯示對話方塊,請建立 {@link |
| android.support.v4.app.DialogFragment} 執行個體並呼叫 {@link android.support.v4.app.DialogFragment#show |
| show()} 來傳送對話方塊片段的 {@link android.support.v4.app.FragmentManager} 和標籤名稱。 |
| </p> |
| |
| <p>如要取得 {@link android.support.v4.app.FragmentManager},請呼叫 |
| {@link android.support.v4.app.FragmentActivity} 中的 |
| {@link android.support.v4.app.FragmentActivity#getSupportFragmentManager()} 或 {@link |
| android.support.v4.app.Fragment} 中的 {@link |
| android.support.v4.app.Fragment#getFragmentManager()}。例如:</p> |
| |
| <pre> |
| public void confirmFireMissiles() { |
| DialogFragment newFragment = new FireMissilesDialogFragment(); |
| newFragment.show(getSupportFragmentManager(), "missiles"); |
| } |
| </pre> |
| |
| <p>第二個引數 {@code "missiles"} 是不重複的標籤名稱,可供系統視需要用於儲存及還原片段狀態。 |
| 此外,該標籤還可讓您呼叫 |
| {@link android.support.v4.app.FragmentManager#findFragmentByTag |
| findFragmentByTag()} 來取得片段的控點。</p> |
| |
| |
| |
| |
| <h2 id="FullscreenDialog">顯示全螢幕對話方塊或內嵌片段</h2> |
| |
| <p>您可能會想建立 UI 設計,讓 UI 片段在某些情況下於該設計中顯示為對話方塊,而不是其他設計中的全螢幕或內嵌片段 (例如視裝置採用螢幕大小而定)。 |
| |
| {@link android.support.v4.app.DialogFragment} 類別能為您提供這樣的彈性,這是因為該類別仍可做為可嵌入的 {@link |
| android.support.v4.app.Fragment} 使用。 |
| </p> |
| |
| <p>不過,您無法使用 {@link android.app.AlertDialog.Builder AlertDialog.Builder} 或其他 {@link android.app.Dialog} 物件來建置這種對話方塊。 |
| 如果您想建立可嵌入的 {@link android.support.v4.app.DialogFragment},請務必在版面配置中定義對話方塊的 UI,然後透過 {@link android.support.v4.app.DialogFragment#onCreateView |
| onCreateView()} 回呼載入版面配置。 |
| |
| |
| </p> |
| |
| <p>以下的 {@link android.support.v4.app.DialogFragment} 範例可顯示為對話方塊或可嵌入片段 (使用名為 <code>purchase_items.xml</code> 的版面配置): |
| </p> |
| |
| <pre> |
| public class CustomDialogFragment extends DialogFragment { |
| /** The system calls this to get the DialogFragment's layout, regardless |
| of whether it's being displayed as a dialog or an embedded fragment. */ |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| // Inflate the layout to use as dialog or embedded fragment |
| return inflater.inflate(R.layout.purchase_items, container, false); |
| } |
| |
| /** The system calls this only when creating the layout in a dialog. */ |
| @Override |
| public Dialog onCreateDialog(Bundle savedInstanceState) { |
| // The only reason you might override this method when using onCreateView() is |
| // to modify any dialog characteristics. For example, the dialog includes a |
| // title by default, but your custom layout might not need it. So here you can |
| // remove the dialog title, but you must call the superclass to get the Dialog. |
| Dialog dialog = super.onCreateDialog(savedInstanceState); |
| dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); |
| return dialog; |
| } |
| } |
| </pre> |
| |
| <p>以下的程式碼可根據螢幕大小,決定要將片段顯示為對話方塊或全螢幕 UI: |
| </p> |
| |
| <pre> |
| public void showDialog() { |
| FragmentManager fragmentManager = getSupportFragmentManager(); |
| CustomDialogFragment newFragment = new CustomDialogFragment(); |
| |
| if (mIsLargeLayout) { |
| // The device is using a large layout, so show the fragment as a dialog |
| newFragment.show(fragmentManager, "dialog"); |
| } else { |
| // The device is smaller, so show the fragment fullscreen |
| FragmentTransaction transaction = fragmentManager.beginTransaction(); |
| // For a little polish, specify a transition animation |
| transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); |
| // To make it fullscreen, use the 'content' root view as the container |
| // for the fragment, which is always the root view for the activity |
| transaction.add(android.R.id.content, newFragment) |
| .addToBackStack(null).commit(); |
| } |
| } |
| </pre> |
| |
| <p>如要進一步瞭解如何進行片段交易,請參閱<a href="{@docRoot}guide/components/fragments.html">片段</a>指南。 |
| </p> |
| |
| <p>在本範例中,<code>mIsLargeLayout</code> 布林值可指定是否要讓目前的裝置採用應用程式的大型版面配置設計 (藉此將這個片段顯示為對話方塊,而不是全螢幕)。 |
| |
| 設定這種布林值的最佳做法,是使用<a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">替代資源</a>值為不同裝置大小宣告<a href="{@docRoot}guide/topics/resources/more-resources.html#Bool">布林資源值</a>。 |
| |
| 例如,以下是適用於不同螢幕大小的 2 種布林資源版本: |
| </p> |
| |
| <p class="code-caption">res/values/bools.xml</p> |
| <pre> |
| <!-- Default boolean values --> |
| <resources> |
| <bool name="large_layout">false</bool> |
| </resources> |
| </pre> |
| |
| <p class="code-caption">res/values-large/bools.xml</p> |
| <pre> |
| <!-- Large screen boolean values --> |
| <resources> |
| <bool name="large_layout">true</bool> |
| </resources> |
| </pre> |
| |
| <p>接著,您可以在呼叫 Activity 的 {@link android.app.Activity#onCreate onCreate()} 方法時初始化 {@code mIsLargeLayout} 值: |
| </p> |
| |
| <pre> |
| boolean mIsLargeLayout; |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.activity_main); |
| |
| mIsLargeLayout = getResources().getBoolean(R.bool.large_layout); |
| } |
| </pre> |
| |
| |
| |
| <h3 id="ActivityAsDialog">針對大型螢幕將 Activity 顯示為對話方塊</h3> |
| |
| <p>您可以針對大型螢幕將 {@link android.app.Activity} 顯示為對話方塊,而不是將對話方塊顯示為全螢幕 UI,藉此達到相同結果。 |
| |
| 您要採用的方法取決於您的應用程式設計,但如果您的應用程式是針對小型螢幕進行設計,將 Activity 顯示為對話方塊通常就能獲得良好效果,而如果您想針對平板電腦改善使用者體驗,請將生命週期較短的 Activity 顯示為對話方塊。 |
| |
| |
| </p> |
| |
| <p>如果只想針對大型螢幕將 Activity 顯示為對話方塊,請為 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code |
| <activity>}</a> 宣示元素套用 {@link android.R.style#Theme_Holo_DialogWhenLarge Theme.Holo.DialogWhenLarge} 主題: |
| |
| </p> |
| |
| <pre> |
| <activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" > |
| </pre> |
| |
| <p>如要進一步瞭解如何運用主題設定 Activity 的樣式,請參閱<a href="{@docRoot}guide/topics/ui/themes.html">樣式和主題</a>指南。</p> |
| |
| |
| |
| <h2 id="DismissingADialog">關閉對話方塊</h2> |
| |
| <p>只要使用者輕觸任何用 {@link android.app.AlertDialog.Builder} 建立的動作按鈕,系統就會為您關閉對話方塊。 |
| </p> |
| |
| <p>此外,系統也會在使用者輕觸對話方塊清單中的項目時,關閉對話方塊,但如果清單採用圓形按鈕或核取方塊,系統就不會關閉對話方塊。 |
| 不過,您可以對 {@link |
| android.support.v4.app.DialogFragment} 呼叫 {@link android.support.v4.app.DialogFragment#dismiss()},藉此手動關閉對話方塊。 |
| </p> |
| |
| <p>如果您需要在對話方塊關閉時執行特定動作,請在 {@link |
| android.support.v4.app.DialogFragment} 中實作 {@link |
| android.support.v4.app.DialogFragment#onDismiss onDismiss()} 方法。 |
| </p> |
| |
| <p>此外,您還可以「取消」<em></em>對話方塊。這種特殊事件可用於指明使用者尚未完成工作便關閉對話方塊。 |
| 如果使用者按下 [返回]<em></em> 按鈕、輕觸對話方塊以外的螢幕畫面,或如果您對 {@link |
| android.app.Dialog} 呼叫 {@link android.app.Dialog#cancel()} (例如藉此回應對話方塊中的 [取消] 按鈕),就會發生這個事件。 |
| |
| </p> |
| |
| <p>如上方範例所示,您可以在 {@link |
| android.support.v4.app.DialogFragment} 類別中實作 {@link android.support.v4.app.DialogFragment#onCancel onCancel()} 來回應取消事件。 |
| </p> |
| |
| <p class="note"><strong>注意:</strong>系統會在發生會呼叫 {@link android.support.v4.app.DialogFragment#onCancel onCancel()} 回呼的事件時呼叫 |
| {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()}。 |
| 不過,如果您呼叫 {@link android.app.Dialog#dismiss Dialog.dismiss()} 或 {@link |
| android.support.v4.app.DialogFragment#dismiss DialogFragment.dismiss()},則系統會呼叫 {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()}「而不是」<em></em>{@link android.support.v4.app.DialogFragment#onCancel onCancel()}。 |
| |
| |
| 因此,我們通常建議您在使用者點擊您對話方塊中的「正面」<em></em>按鈕以便將對話方塊從檢視移除時,呼叫 {@link android.support.v4.app.DialogFragment#dismiss dismiss()}。 |
| |
| </p> |
| |
| |