1page.title=Hộp thoại
2page.tags=alertdialog,dialogfragment
3
4@jd:body
5
6
7
8<div id="qv-wrapper">
9  <div id="qv">
10    <h2>Trong tài liệu này</h2>
11<ol>
12  <li><a href="#DialogFragment">Tạo một Phân đoạn Hộp thoại</a></li>
13  <li><a href="#AlertDialog">Xây dựng một Hộp thoại Cảnh báo</a>
14    <ol>
15      <li><a href="#AddingButtons">Thêm nút</a></li>
16      <li><a href="#AddingAList">Thêm một danh sách</a></li>
17      <li><a href="#CustomLayout">Tạo một Bố trí Tùy chỉnh</a></li>
18    </ol>
19  </li>
20  <li><a href="#PassingEvents">Chuyển Sự kiện lại Máy chủ của Hộp thoại</a></li>
21  <li><a href="#ShowingADialog">Hiển thị một Hộp thoại</a></li>
22  <li><a href="#FullscreenDialog">Hiển thị một Hộp thoại Toàn màn hình hoặc dạng một Phân đoạn Nhúng</a>
23    <ol>
24      <li><a href="#ActivityAsDialog">Hiển thị một hoạt động dưới dạng một hộp thoại trên màn hình lớn</a></li>
25    </ol>
26  </li>
27  <li><a href="#DismissingADialog">Bỏ một Hộp thoại</a></li>
28</ol>
29
30    <h2>Lớp khóa</h2>
31    <ol>
32      <li>{@link android.app.DialogFragment}</li>
33      <li>{@link android.app.AlertDialog}</li>
34    </ol>
35
36    <h2>Xem thêm</h2>
37    <ol>
38      <li><a href="{@docRoot}design/building-blocks/dialogs.html">Hướng dẫn thiết kế hộp thoại</a></li>
39      <li><a href="{@docRoot}guide/topics/ui/controls/pickers.html">Bộ chọn</a> (Hộp thoại Ngày/Giờ)</li>
40    </ol>
41  </div>
42</div>
43
44<p>Hộp thoại là một cửa sổ nhỏ có chức năng nhắc người dùng
45đưa ra một quyết định hoặc nhập thông tin bổ sung. Hộp thoại không lấp kín màn hình và
46thường được sử dụng cho các sự kiện mô thái yêu cầu người dùng phải thực hiện một hành động trước khi có thể đi tiếp.</p>
47
48<div class="note design">
49<p><strong>Thiết kế Hộp thoại</strong></p>
50  <p>Để biết thông tin về cách thiết kế hộp thoại của bạn, bao gồm các đề xuất
51  về ngôn ngữ, hãy đọc hướng dẫn thiết kế <a href="{@docRoot}design/building-blocks/dialogs.html">Hộp thoại</a>.</p>
52</div>
53
54<img src="{@docRoot}images/ui/dialogs.png" />
55
56<p>Lớp {@link android.app.Dialog} là lớp cơ sở cho hộp thoại, nhưng bạn
57nên tránh khởi tạo {@link android.app.Dialog} một cách trực tiếp.
58Thay vào đó, hãy sử dụng một trong các lớp con sau:</p>
59<dl>
60  <dt>{@link android.app.AlertDialog}</dt>
61  <dd>Hộp thoại có thể hiển thị một tiêu đề, tối đa ba nút, một danh sách
62    các mục có thể chọn, hoặc một bố trí tùy chỉnh.</dd>
63  <dt>{@link android.app.DatePickerDialog} hoặc {@link android.app.TimePickerDialog}</dt>
64  <dd>Hộp thoại với một UI được xác định trước, cho phép người dùng chọn ngày hoặc giờ.</dd>
65</dl>
66
67<div class="sidebox">
68<h2>Tránh ProgressDialog</h2>
69<p>Android có một lớp hộp thoại khác gọi là
70{@link android.app.ProgressDialog}, nó hiển thị một hộp thoại với một thanh tiến độ. Tuy nhiên, nếu bạn
71cần chỉ báo tiến độ tải hoặc chưa xác định, thay vào đó, bạn nên tuân theo hướng dẫn
72thiết kế dành cho <a href="{@docRoot}design/building-blocks/progress.html">Tiến độ &amp;
73Hoạt động</a> và sử dụng một {@link android.widget.ProgressBar} trong bố trí của mình.</p>
74</div>
75
76<p>Những lớp này định nghĩa kiểu và cấu trúc cho hộp thoại của bạn, nhưng bạn nên
77sử dụng một {@link android.support.v4.app.DialogFragment} làm bộ chứa cho hộp thoại của mình.
78Lớp {@link android.support.v4.app.DialogFragment} sẽ cung cấp tất cả điều khiển mà
79bạn cần để tạo hộp thoại của mình và quản lý diện mạo của hộp thoại, thay vì gọi ra các phương pháp
80trên đối tượng {@link android.app.Dialog}.</p>
81
82<p>Việc sử dụng {@link android.support.v4.app.DialogFragment} để quản lý hộp thoại
83sẽ đảm bảo rằng nó xử lý đúng các sự kiện vòng đời
84chẳng hạn như khi người dùng nhấn nút <em>Quay lại</em> hoặc xoay màn hình. Lớp {@link
85android.support.v4.app.DialogFragment} cũng cho phép bạn sử dụng lại UI của hộp thoại như một
86thành phần có thể nhúng trong một UI rộng hơn, giống như một {@link
87android.support.v4.app.Fragment} truyền thống (chẳng hạn như khi bạn muốn UI hộp thoại xuất hiện khác đi
88trên các màn hình lớn và nhỏ).</p>
89
90<p>Các phần sau trong hướng dẫn này mô tả cách sử dụng {@link
91android.support.v4.app.DialogFragment} kết hợp với một đối tượng {@link android.app.AlertDialog}
92. Nếu muốn tạo một bộ chọn ngày hoặc giờ, thay vào đó, bạn nên đọc hướng dẫn
93<a href="{@docRoot}guide/topics/ui/controls/pickers.html">Bộ chọn</a>.</p>
94
95<p class="note"><strong>Lưu ý:</strong>
96Vì lớp {@link android.app.DialogFragment} ban đầu được bổ sung cùng với
97Android 3.0 (API mức 11), tài liệu này mô tả cách sử dụng lớp {@link
98android.support.v4.app.DialogFragment} được cung cấp kèm <a href="{@docRoot}tools/support-library/index.html">Thư viện Hỗ trợ</a>. Bằng cách thêm thư viện này
99vào ứng dụng của mình, bạn có thể sử dụng {@link android.support.v4.app.DialogFragment} và nhiều loại
100API khác trên các thiết bị chạy Android 1.6 hoặc cao hơn. Nếu phiên bản tối thiểu mà ứng dụng của bạn hỗ trợ
101là API mức 11 hoặc cao hơn, khi đó bạn có thể sử dụng phiên bản khuôn khổ của {@link
102android.app.DialogFragment}, nhưng hãy chú ý rằng các liên kết trong tài liệu này dành cho các API
103thư viện hỗ  trợ. Khi sử dụng thư viện hỗ trợ,
104hãy nhớ rằng bạn nhập lớp <code>android.support.v4.app.DialogFragment</code>
105chứ <em>không phải</em> <code>android.app.DialogFragment</code>.</p>
106
107
108<h2 id="DialogFragment">Tạo một Phân đoạn Hộp thoại</h2>
109
110<p>Bạn có thể hoàn thành nhiều loại thiết kế hộp thoại&mdash;bao gồm
111bố trí tùy chỉnh và những bố trí được mô tả trong hướng dẫn thiết kế <a href="{@docRoot}design/building-blocks/dialogs.html">Hộp thoại</a>
112&mdash;bằng cách mở rộng
113{@link android.support.v4.app.DialogFragment} và tạo một {@link android.app.AlertDialog}
114trong phương pháp gọi lại {@link android.support.v4.app.DialogFragment#onCreateDialog
115onCreateDialog()}.</p>
116
117<p>Ví dụ, sau đây là một {@link android.app.AlertDialog} cơ bản được quản lý bên trong
118một {@link android.support.v4.app.DialogFragment}:</p>
119
120<pre>
121public class FireMissilesDialogFragment extends DialogFragment {
122    &#64;Override
123    public Dialog onCreateDialog(Bundle savedInstanceState) {
124        // Use the Builder class for convenient dialog construction
125        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
126        builder.setMessage(R.string.dialog_fire_missiles)
127               .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
128                   public void onClick(DialogInterface dialog, int id) {
129                       // FIRE ZE MISSILES!
130                   }
131               })
132               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
133                   public void onClick(DialogInterface dialog, int id) {
134                       // User cancelled the dialog
135                   }
136               });
137        // Create the AlertDialog object and return it
138        return builder.create();
139    }
140}
141</pre>
142
143<div class="figure" style="width:290px;margin:0 0 0 20px">
144<img src="{@docRoot}images/ui/dialog_buttons.png" alt="" />
145<p class="img-caption"><strong>Hình 1.</strong>
146Hộp thoại với một thông báo và hai nút hành động.</p>
147</div>
148
149<p>Lúc này, khi bạn tạo một thực thể thuộc lớp này và gọi {@link
150android.support.v4.app.DialogFragment#show show()} trên đối tượng đó, hộp thoại sẽ xuất hiện
151như minh họa trong hình 1.</p>
152
153<p>Phần tiếp theo mô tả thêm về việc sử dụng các API {@link android.app.AlertDialog.Builder}
154để tạo hộp thoại.</p>
155
156<p>Tùy vào độ phức tạp của hộp thoại của bạn, bạn có thể triển khai nhiều loại phương pháp gọi lại khác
157trong {@link android.support.v4.app.DialogFragment}, bao gồm tất cả
158<a href="{@docRoot}guide/components/fragments.html#Lifecycle">phương pháp vòng đời phân đoạn</a> cơ bản.
159
160
161
162
163
164<h2 id="AlertDialog">Xây dựng một Hộp thoại Cảnh báo</h2>
165
166
167<p>Lớp {@link android.app.AlertDialog} cho phép bạn xây dựng nhiều loại thiết kế hộp thoại và
168thường là lớp hộp thoại duy nhất mà bạn sẽ cần.
169Như được minh họa trong hình 2, có ba vùng trên một hộp thoại cảnh báo:</p>
170
171<div class="figure" style="width:311px;margin-top:0">
172<img src="{@docRoot}images/ui/dialogs_regions.png" alt="" style="margin-bottom:0" />
173<p class="img-caption"><strong>Hình 2.</strong> Bố trí của một hộp thoại.</p>
174</div>
175
176<ol>
177<li><b>Tiêu đề</b>
178  <p>Tiêu đề không bắt buộc và chỉ nên được sử dụng khi vùng nội dung
179  bị chiếm bởi một thông báo chi tiết, một danh sách, hay một bố trí tùy chỉnh. Nếu bạn cần nêu
180  một thông báo hoặc câu hỏi đơn giản (chẳng hạn như hộp thoại trong hình 1), bạn không cần tiêu đề.</li>
181<li><b>Vùng nội dung</b>
182  <p>Vùng này có thể hiển thị một thông báo, danh sách, hay bố trí tùy chỉnh khác.</p></li>
183<li><b>Nút hành động</b>
184  <p>Sẽ không có quá ba nút hành động trong một hộp thoại.</p></li>
185</ol>
186
187<p>Lớp {@link android.app.AlertDialog.Builder}
188cung cấp các API cho phép bạn tạo một {@link android.app.AlertDialog}
189với những kiểu nội dung này, bao gồm một bố trí tùy chỉnh.</p>
190
191<p>Để xây dựng một {@link android.app.AlertDialog}:</p>
192
193<pre>
194<b>// 1. Instantiate an {@link android.app.AlertDialog.Builder} with its constructor</b>
195AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
196
197<b>// 2. Chain together various setter methods to set the dialog characteristics</b>
198builder.setMessage(R.string.dialog_message)
199       .setTitle(R.string.dialog_title);
200
201<b>// 3. Get the {@link android.app.AlertDialog} from {@link android.app.AlertDialog.Builder#create()}</b>
202AlertDialog dialog = builder.create();
203</pre>
204
205<p>Các chủ đề sau cho biết cách định nghĩa các thuộc tính hộp thoại khác nhau bằng cách
206sử dụng lớp {@link android.app.AlertDialog.Builder}.</p>
207
208
209
210
211<h3 id="AddingButtons">Thêm nút</h3>
212
213<p>Để thêm các nút hành động như trong hình 2,
214hãy gọi các phương pháp {@link android.app.AlertDialog.Builder#setPositiveButton setPositiveButton()} và
215{@link android.app.AlertDialog.Builder#setNegativeButton setNegativeButton()}:</p>
216
217<pre style="clear:right">
218AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
219// Add the buttons
220builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
221           public void onClick(DialogInterface dialog, int id) {
222               // User clicked OK button
223           }
224       });
225builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
226           public void onClick(DialogInterface dialog, int id) {
227               // User cancelled the dialog
228           }
229       });
230// Set other dialog properties
231...
232
233// Create the AlertDialog
234AlertDialog dialog = builder.create();
235</pre>
236
237<p>Các phương pháp <code>set...Button()</code> yêu cầu một tiêu đề cho nút (được cung cấp
238bởi một <a href="{@docRoot}guide/topics/resources/string-resource.html">tài nguyên xâu</a>) và một
239{@link android.content.DialogInterface.OnClickListener} có chức năng định nghĩa hành động sẽ tiến hành
240khi người dùng nhấn nút.</p>
241
242<p>Có ba nút hành động khác nhau mà bạn có thể thêm:</p>
243<dl>
244  <dt>Tích cực</dt>
245  <dd>Bạn nên sử dụng nút này để chấp nhận và tiếp tục với hành động (hành động "OK").</dd>
246  <dt>Tiêu cực</dt>
247  <dd>Bạn nên sử dụng nút này để hủy bỏ hành động.</dd>
248  <dt>Trung lập</dt>
249  <dd>Bạn nên sử dụng nút này khi người dùng có thể không muốn tiếp tục với hành động,
250  nhưng không hẳn muốn hủy bỏ. Nó nằm ở giữa nút
251  tích cực và tiêu cực. Ví dụ, hành động có thể là "Nhắc tôi sau."</dd>
252</dl>
253
254<p>Bạn chỉ có thể thêm một nút mỗi loại vào một {@link
255android.app.AlertDialog}. Nghĩa là, bạn không thể có nhiều hơn một nút "tích cực".</p>
256
257
258
259<div class="figure" style="width:290px;margin:0 0 0 40px">
260<img src="{@docRoot}images/ui/dialog_list.png" alt="" />
261<p class="img-caption"><strong>Hình 3.</strong>
262Hộp thoại có tiêu đề và danh sách.</p>
263</div>
264
265<h3 id="AddingAList">Thêm một danh sách</h3>
266
267<p>Có ba loại danh sách có sẵn với các API {@link android.app.AlertDialog}:</p>
268<ul>
269<li>Danh sách một lựa chọn truyền thống</li>
270<li>Danh sách một lựa chọn cố định (nút chọn một)</li>
271<li>Danh sách nhiều lựa chọn cố định (hộp kiểm)</li>
272</ul>
273
274<p>Để tạo danh sách một lựa chọn như danh sách trong hình 3,
275hãy sử dụng phương pháp {@link android.app.AlertDialog.Builder#setItems setItems()}:</p>
276
277<pre style="clear:right">
278&#64;Override
279public Dialog onCreateDialog(Bundle savedInstanceState) {
280    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
281    builder.setTitle(R.string.pick_color)
282           .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
283               public void onClick(DialogInterface dialog, int which) {
284               // The 'which' argument contains the index position
285               // of the selected item
286           }
287    });
288    return builder.create();
289}
290</pre>
291
292<p>Vì danh sách xuất hiện trong vùng nội dung của hộp thoại,
293hộp thoại không thể hiển thị cả thông báo và danh sách và bạn nên đặt một tiêu đề cho hộp thoại
294bằng {@link android.app.AlertDialog.Builder#setTitle setTitle()}.
295Để chỉ định các mục cho danh sách, hãy gọi {@link
296android.app.AlertDialog.Builder#setItems setItems()}, chuyển một mảng.
297Hoặc, bạn có thể chỉ định một danh sách bằng cách sử dụng {@link
298android.app.AlertDialog.Builder#setAdapter setAdapter()}. Điều này cho phép bạn hỗ trợ danh sách
299bằng dữ liệu động (chẳng hạn như từ một cơ sở dữ liệu) bằng cách sử dụng {@link android.widget.ListAdapter}.</p>
300
301<p>Nếu bạn chọn hỗ trợ danh sách của mình bằng một {@link android.widget.ListAdapter},
302hãy luôn sử dụng {@link android.support.v4.content.Loader} sao cho nội dung tải
303không đồng bộ. Điều này được mô tả thêm trong hướng dẫn
304<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Xây dựng Bố trí
305bằng một Trình điều hợp</a> và <a href="{@docRoot}guide/components/loaders.html">Trình tải</a>
306.</p>
307
308<p class="note"><strong>Lưu ý:</strong> Theo mặc định, chạm vào một mục danh sách sẽ bỏ hộp thoại,
309trừ khi bạn đang sử dụng một trong các danh sách lựa chọn cố định sau.</p>
310
311<div class="figure" style="width:290px;margin:-30px 0 0 40px">
312<img src="{@docRoot}images/ui/dialog_checkboxes.png" />
313<p class="img-caption"><strong>Hình 4.</strong>
314Danh sách nhiều mục lựa chọn.</p>
315</div>
316
317
318<h4 id="Checkboxes">Thêm một danh sách nhiều lựa chọn hoặc một lựa chọn cố định</h4>
319
320<p>Để thêm một danh sách nhiều lựa chọn (hộp kiểm) hoặc
321một lựa chọn (nút chọn một), hãy sử dụng các phương pháp
322{@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String,
323DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} hoặc
324{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
325setSingleChoiceItems()} tương ứng.</p>
326
327<p>Ví dụ, sau đây là cách bạn có thể tạo một danh sách nhiều lựa chọn như
328danh sách được minh họa trong hình 4 giúp lưu các mục
329được chọn trong một {@link java.util.ArrayList}:</p>
330
331<pre style="clear:right">
332&#64;Override
333public Dialog onCreateDialog(Bundle savedInstanceState) {
334    mSelectedItems = new ArrayList();  // Where we track the selected items
335    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
336    // Set the dialog title
337    builder.setTitle(R.string.pick_toppings)
338    // Specify the list array, the items to be selected by default (null for none),
339    // and the listener through which to receive callbacks when items are selected
340           .setMultiChoiceItems(R.array.toppings, null,
341                      new DialogInterface.OnMultiChoiceClickListener() {
342               &#64;Override
343               public void onClick(DialogInterface dialog, int which,
344                       boolean isChecked) {
345                   if (isChecked) {
346                       // If the user checked the item, add it to the selected items
347                       mSelectedItems.add(which);
348                   } else if (mSelectedItems.contains(which)) {
349                       // Else, if the item is already in the array, remove it
350                       mSelectedItems.remove(Integer.valueOf(which));
351                   }
352               }
353           })
354    // Set the action buttons
355           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
356               &#64;Override
357               public void onClick(DialogInterface dialog, int id) {
358                   // User clicked OK, so save the mSelectedItems results somewhere
359                   // or return them to the component that opened the dialog
360                   ...
361               }
362           })
363           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
364               &#64;Override
365               public void onClick(DialogInterface dialog, int id) {
366                   ...
367               }
368           });
369
370    return builder.create();
371}
372</pre>
373
374<p>Mặc dù cả danh sách truyền thống và danh sách có nút chọn một
375đều cung cấp hành động "một lựa chọn", bạn nên sử dụng {@link
376android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
377setSingleChoiceItems()} nếu bạn muốn cố định lựa chọn của người dùng.
378Cụ thể, nếu việc mở hộp thoại lại sau này báo hiệu lựa chọn hiện tại của người dùng, khi đó
379bạn hãy tạo một danh sách với các nút chọn một.</p>
380
381
382
383
384
385<h3 id="CustomLayout">Tạo một Bố trí Tùy chỉnh</h3>
386
387<div class="figure" style="width:290px;margin:-30px 0 0 40px">
388<img src="{@docRoot}images/ui/dialog_custom.png" alt="" />
389<p class="img-caption"><strong>Hình 5.</strong> Một bố trí hộp thoại tùy chỉnh.</p>
390</div>
391
392<p>Nếu bạn muốn một bố trí tùy chỉnh trong một hộp thoại, hãy tạo một bố trí và thêm nó vào một
393{@link android.app.AlertDialog} bằng cách gọi {@link
394android.app.AlertDialog.Builder#setView setView()} trên đối tượng {@link
395android.app.AlertDialog.Builder} của bạn.</p>
396
397<p>Theo mặc định, bố trí tùy chỉnh sẽ lấp đầy cửa sổ hộp thoại, nhưng bạn vẫn có thể
398sử dụng các phương pháp {@link android.app.AlertDialog.Builder} để thêm nút và tiêu đề.</p>
399
400<p>Ví dụ, sau đây là tệp bố trí cho hộp thoại trong Hình 5:</p>
401
402<p style="clear:right" class="code-caption">res/layout/dialog_signin.xml</p>
403<pre>
404&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
405    android:orientation="vertical"
406    android:layout_width="wrap_content"
407    android:layout_height="wrap_content">
408    &lt;ImageView
409        android:src="@drawable/header_logo"
410        android:layout_width="match_parent"
411        android:layout_height="64dp"
412        android:scaleType="center"
413        android:background="#FFFFBB33"
414        android:contentDescription="@string/app_name" />
415    &lt;EditText
416        android:id="@+id/username"
417        android:inputType="textEmailAddress"
418        android:layout_width="match_parent"
419        android:layout_height="wrap_content"
420        android:layout_marginTop="16dp"
421        android:layout_marginLeft="4dp"
422        android:layout_marginRight="4dp"
423        android:layout_marginBottom="4dp"
424        android:hint="@string/username" />
425    &lt;EditText
426        android:id="@+id/password"
427        android:inputType="textPassword"
428        android:layout_width="match_parent"
429        android:layout_height="wrap_content"
430        android:layout_marginTop="4dp"
431        android:layout_marginLeft="4dp"
432        android:layout_marginRight="4dp"
433        android:layout_marginBottom="16dp"
434        android:fontFamily="sans-serif"
435        android:hint="@string/password"/>
436&lt;/LinearLayout>
437</pre>
438
439<p class="note"><strong>Mẹo:</strong> Theo mặc định, khi bạn đặt một phần tử {@link android.widget.EditText}
440để sử dụng kiểu đầu vào {@code "textPassword"}, họ phông được đặt thành đơn cách, vì thế
441bạn nên đổi họ phông thành {@code "sans-serif"} sao cho cả hai trường văn bản đều sử dụng
442một kiểu phông thống nhất.</p>
443
444<p>Để bung bố trí ra trong {@link android.support.v4.app.DialogFragment} của bạn,
445hãy lấy một {@link android.view.LayoutInflater} với
446{@link android.app.Activity#getLayoutInflater()} và gọi
447{@link android.view.LayoutInflater#inflate inflate()}, trong đó tham số đầu tiên
448là ID tài nguyên bố trí và tham số thứ hai là một dạng xem mẹ cho bố trí.
449Khi đó, bạn có thể gọi {@link android.app.AlertDialog#setView setView()}
450để đặt bố trí vào một hộp thoại.</p>
451
452<pre>
453&#64;Override
454public Dialog onCreateDialog(Bundle savedInstanceState) {
455    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
456    // Get the layout inflater
457    LayoutInflater inflater = getActivity().getLayoutInflater();
458
459    // Inflate and set the layout for the dialog
460    // Pass null as the parent view because its going in the dialog layout
461    builder.setView(inflater.inflate(R.layout.dialog_signin, null))
462    // Add action buttons
463           .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
464               &#64;Override
465               public void onClick(DialogInterface dialog, int id) {
466                   // sign in the user ...
467               }
468           })
469           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
470               public void onClick(DialogInterface dialog, int id) {
471                   LoginDialogFragment.this.getDialog().cancel();
472               }
473           });
474    return builder.create();
475}
476</pre>
477
478<div class="note">
479<p><strong>Mẹo:</strong> Nếu bạn muốn một hộp thoại tùy chỉnh,
480thay vào đó, bạn có thể hiển thị {@link android.app.Activity} như là một hộp thoại
481thay vì sử dụng các API {@link android.app.Dialog}. Chỉ cần tạo một hoạt động và đặt chủ đề của nó thành
482{@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog}
483trong phần tử bản kê khai <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
484&lt;activity&gt;}</a>:</p>
485
486<pre>
487&lt;activity android:theme="&#64;android:style/Theme.Holo.Dialog" >
488</pre>
489<p>Vậy là xong. Lúc này, hoạt động sẽ hiển thị một cửa sổ hộp thoại thay vì toàn màn hình.</p>
490</div>
491
492
493
494<h2 id="PassingEvents">Chuyển Sự kiện lại Máy chủ của Hộp thoại</h2>
495
496<p>Khi người dùng chạm vào một trong các nút hành động của hộp thoại hoặc chọn một mục từ danh sách của hộp thoại,
497{@link android.support.v4.app.DialogFragment} của bạn có thể tự thực hiện hành động
498cần thiết, nhưng thường thì bạn sẽ muốn chuyển sự kiện tới hoạt động hoặc phân đoạn
499đã mở hộp thoại. Để làm điều này, hãy định nghĩa một giao diện bằng một phương pháp cho mỗi loại sự kiện nhấp.
500Sau đó, triển khai giao diện đó trong thành phần chủ mà sẽ
501nhận sự kiện hành động từ hộp thoại.</p>
502
503<p>Ví dụ, sau đây là một {@link android.support.v4.app.DialogFragment} có chức năng định nghĩa một
504giao diện mà thông qua đó, nó sẽ chuyển các sự kiện lại cho hoạt động chủ:</p>
505
506<pre>
507public class NoticeDialogFragment extends DialogFragment {
508
509    /* The activity that creates an instance of this dialog fragment must
510     * implement this interface in order to receive event callbacks.
511     * Each method passes the DialogFragment in case the host needs to query it. */
512    public interface NoticeDialogListener {
513        public void onDialogPositiveClick(DialogFragment dialog);
514        public void onDialogNegativeClick(DialogFragment dialog);
515    }
516
517    // Use this instance of the interface to deliver action events
518    NoticeDialogListener mListener;
519
520    // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
521    &#64;Override
522    public void onAttach(Activity activity) {
523        super.onAttach(activity);
524        // Verify that the host activity implements the callback interface
525        try {
526            // Instantiate the NoticeDialogListener so we can send events to the host
527            mListener = (NoticeDialogListener) activity;
528        } catch (ClassCastException e) {
529            // The activity doesn't implement the interface, throw exception
530            throw new ClassCastException(activity.toString()
531                    + " must implement NoticeDialogListener");
532        }
533    }
534    ...
535}
536</pre>
537
538<p>Hoạt động lưu giữ hộp thoại sẽ tạo một thực thể của hộp thoại
539bằng hàm dựng của phân đoạn hộp thoại và nhận sự kiện
540của hộp thoại thông qua triển khai giao diện {@code NoticeDialogListener}:</p>
541
542<pre>
543public class MainActivity extends FragmentActivity
544                          implements NoticeDialogFragment.NoticeDialogListener{
545    ...
546
547    public void showNoticeDialog() {
548        // Create an instance of the dialog fragment and show it
549        DialogFragment dialog = new NoticeDialogFragment();
550        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
551    }
552
553    // The dialog fragment receives a reference to this Activity through the
554    // Fragment.onAttach() callback, which it uses to call the following methods
555    // defined by the NoticeDialogFragment.NoticeDialogListener interface
556    &#64;Override
557    public void onDialogPositiveClick(DialogFragment dialog) {
558        // User touched the dialog's positive button
559        ...
560    }
561
562    &#64;Override
563    public void onDialogNegativeClick(DialogFragment dialog) {
564        // User touched the dialog's negative button
565        ...
566    }
567}
568</pre>
569
570<p>Vì hoạt động chủ sẽ triển khai {@code NoticeDialogListener}&mdash;, được
571thực thi bởi phương pháp gọi lại {@link android.support.v4.app.Fragment#onAttach onAttach()}
572minh họa bên trên,&mdash;phân đoạn hộp thoại có thể sử dụng các phương pháp gọi lại
573giao diện để chuyển các sự kiện nhấp cho hoạt động:</p>
574
575<pre>
576public class NoticeDialogFragment extends DialogFragment {
577    ...
578
579    &#64;Override
580    public Dialog onCreateDialog(Bundle savedInstanceState) {
581        // Build the dialog and set up the button click handlers
582        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
583        builder.setMessage(R.string.dialog_fire_missiles)
584               .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
585                   public void onClick(DialogInterface dialog, int id) {
586                       // Send the positive button event back to the host activity
587                       mListener.onDialogPositiveClick(NoticeDialogFragment.this);
588                   }
589               })
590               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
591                   public void onClick(DialogInterface dialog, int id) {
592                       // Send the negative button event back to the host activity
593                       mListener.onDialogNegativeClick(NoticeDialogFragment.this);
594                   }
595               });
596        return builder.create();
597    }
598}
599</pre>
600
601
602
603<h2 id="ShowingADialog">Hiển thị một Hộp thoại</h2>
604
605<p>Khi bạn muốn hiển thị hộp thoại của mình, hãy tạo một thực thể {@link
606android.support.v4.app.DialogFragment} của bạn và gọi {@link android.support.v4.app.DialogFragment#show
607show()}, chuyển {@link android.support.v4.app.FragmentManager} và một tên tag
608cho phân đoạn hộp thoại.</p>
609
610<p>Bạn có thể nhận được {@link android.support.v4.app.FragmentManager} bằng cách gọi
611{@link android.support.v4.app.FragmentActivity#getSupportFragmentManager()} từ
612{@link android.support.v4.app.FragmentActivity} hoặc {@link
613android.support.v4.app.Fragment#getFragmentManager()} từ một {@link
614android.support.v4.app.Fragment}. Ví dụ:</p>
615
616<pre>
617public void confirmFireMissiles() {
618    DialogFragment newFragment = new FireMissilesDialogFragment();
619    newFragment.show(getSupportFragmentManager(), "missiles");
620}
621</pre>
622
623<p>Tham đối thứ hai, {@code "missiles"}, là một tên tag duy nhất mà hệ thống sử dụng để lưu
624và khôi phục trạng thái của phân đoạn khi cần thiết. Tag cũng cho phép bạn nhận một điều khiển (handle) cho
625phân đoạn bằng cách gọi {@link android.support.v4.app.FragmentManager#findFragmentByTag
626findFragmentByTag()}.</p>
627
628
629
630
631<h2 id="FullscreenDialog">Hiển thị một Hộp thoại Toàn màn hình hoặc dạng một Phân đoạn Nhúng</h2>
632
633<p>Bạn có thể có một thiết kế UI mà trong đó bạn muốn một phần UI xuất hiện như một hộp thoại trong một số
634tình huống, nhưng ở dưới dạng toàn màn hình hoặc phân đoạn nhúng trong trường hợp khác (có thể phụ thuộc
635vào thiết bị là màn hình lớn hay nhỏ). Lớp {@link android.support.v4.app.DialogFragment}
636cung cấp cho bạn sự linh hoạt này vì nó vẫn có thể đóng vai trò như một {@link
637android.support.v4.app.Fragment} nhúng được.</p>
638
639<p>Tuy nhiên, bạn không thể sử dụng {@link android.app.AlertDialog.Builder AlertDialog.Builder}
640hay các đối tượng {@link android.app.Dialog} khác để xây dựng hộp thoại trong trường hợp này. Nếu
641bạn muốn {@link android.support.v4.app.DialogFragment} có thể
642nhúng được, bạn phải định nghĩa UI của hộp thoại trong một bố trí, rồi tải bố trí đó trong lệnh gọi lại
643{@link android.support.v4.app.DialogFragment#onCreateView
644onCreateView()}.</p>
645
646<p>Sau đây là một ví dụ {@link android.support.v4.app.DialogFragment} có thể xuất hiện như một
647hộp thoại hoặc phân đoạn nhúng được (sử dụng một bố trí có tên gọi <code>purchase_items.xml</code>):</p>
648
649<pre>
650public class CustomDialogFragment extends DialogFragment {
651    /** The system calls this to get the DialogFragment's layout, regardless
652        of whether it's being displayed as a dialog or an embedded fragment. */
653    &#64;Override
654    public View onCreateView(LayoutInflater inflater, ViewGroup container,
655            Bundle savedInstanceState) {
656        // Inflate the layout to use as dialog or embedded fragment
657        return inflater.inflate(R.layout.purchase_items, container, false);
658    }
659
660    /** The system calls this only when creating the layout in a dialog. */
661    &#64;Override
662    public Dialog onCreateDialog(Bundle savedInstanceState) {
663        // The only reason you might override this method when using onCreateView() is
664        // to modify any dialog characteristics. For example, the dialog includes a
665        // title by default, but your custom layout might not need it. So here you can
666        // remove the dialog title, but you must call the superclass to get the Dialog.
667        Dialog dialog = super.onCreateDialog(savedInstanceState);
668        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
669        return dialog;
670    }
671}
672</pre>
673
674<p>Và sau đây là một số mã quyết định xem hiển thị phân đoạn như một hộp thoại
675hay UI toàn màn hình, dựa vào kích cỡ màn hình:</p>
676
677<pre>
678public void showDialog() {
679    FragmentManager fragmentManager = getSupportFragmentManager();
680    CustomDialogFragment newFragment = new CustomDialogFragment();
681
682    if (mIsLargeLayout) {
683        // The device is using a large layout, so show the fragment as a dialog
684        newFragment.show(fragmentManager, "dialog");
685    } else {
686        // The device is smaller, so show the fragment fullscreen
687        FragmentTransaction transaction = fragmentManager.beginTransaction();
688        // For a little polish, specify a transition animation
689        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
690        // To make it fullscreen, use the 'content' root view as the container
691        // for the fragment, which is always the root view for the activity
692        transaction.add(android.R.id.content, newFragment)
693                   .addToBackStack(null).commit();
694    }
695}
696</pre>
697
698<p>Để biết thêm thông tin về việc thực hiện các giao tác phân đoạn, hãy xem hướng dẫn
699<a href="{@docRoot}guide/components/fragments.html">Phân đoạn</a>.</p>
700
701<p>Trong ví dụ này, boolean <code>mIsLargeLayout</code> chỉ định liệu thiết bị hiện tại
702có nên sử dụng thiết kế bố trí lớn của ứng dụng (và vì thế, nó hiển thị phân đoạn này như một hộp thoại thay vì
703toàn màn hình) hay không. Cách tốt nhất để đặt loại boolean này đó là khai báo một
704<a href="{@docRoot}guide/topics/resources/more-resources.html#Bool">giá trị tài nguyên bool</a>
705bằng một giá trị <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">tài nguyên thay thế</a> cho các kích cỡ màn hình khác nhau. Ví dụ, sau đây là hai
706phiên bản của tài nguyên bool cho các kích cỡ màn hình khác nhau:</p>
707
708<p class="code-caption">res/values/bools.xml</p>
709<pre>
710&lt;!-- Default boolean values -->
711&lt;resources>
712    &lt;bool name="large_layout">false&lt;/bool>
713&lt;/resources>
714</pre>
715
716<p class="code-caption">res/values-large/bools.xml</p>
717<pre>
718&lt;!-- Large screen boolean values -->
719&lt;resources>
720    &lt;bool name="large_layout">true&lt;/bool>
721&lt;/resources>
722</pre>
723
724<p>Khi đó, bạn có thể khởi tạo giá trị {@code mIsLargeLayout} trong phương pháp
725{@link android.app.Activity#onCreate onCreate()} của hoạt động:</p>
726
727<pre>
728boolean mIsLargeLayout;
729
730&#64;Override
731public void onCreate(Bundle savedInstanceState) {
732    super.onCreate(savedInstanceState);
733    setContentView(R.layout.activity_main);
734
735    mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
736}
737</pre>
738
739
740
741<h3 id="ActivityAsDialog">Hiển thị một hoạt động dưới dạng một hộp thoại trên màn hình lớn</h3>
742
743<p>Thay vì hiển thị một hộp thoại thành UI toàn màn hình trên các màn hình nhỏ, bạn có thể đạt được
744kết quả tương tự bằng cách hiển thị một {@link android.app.Activity} thành một hộp thoại trên
745màn hình lớn. Phương pháp mà bạn chọn phụ thuộc vào thiết kế ứng dụng của bạn, nhưng
746việc hiển thị một hoạt động thành một hộp thoại thường có ích khi ứng dụng của bạn đã được thiết kế cho màn hình
747nhỏ và bạn muốn cải thiện trải nghiệm trên máy tính bảng bằng cách hiển thị một hoạt động có vòng đời ngắn
748thành một hộp thoại.</p>
749
750<p>Để hiển thị một hoạt động thành một hộp thoại chỉ khi trên màn hình lớn,
751hãy áp dụng chủ đề {@link android.R.style#Theme_Holo_DialogWhenLarge Theme.Holo.DialogWhenLarge}
752cho phần tử bản kê khai <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
753&lt;activity&gt;}</a>:</p>
754
755<pre>
756&lt;activity android:theme="&#64;android:style/Theme.Holo.DialogWhenLarge" >
757</pre>
758
759<p>Để biết thêm thông tin về việc tạo kiểu cho các hoạt động của bạn bằng chủ đề, hãy xem hướng dẫn <a href="{@docRoot}guide/topics/ui/themes.html">Kiểu và Chủ đề</a>.</p>
760
761
762
763<h2 id="DismissingADialog">Bỏ một Hộp thoại</h2>
764
765<p>Khi người dùng chạm vào bất kỳ nút hành động nào được tạo bằng
766{@link android.app.AlertDialog.Builder}, hệ thống sẽ bỏ hộp thoại cho bạn.</p>
767
768<p>Hệ thống cũng bỏ hộp thoại khi người dùng chạm vào một mục trong một danh sách hộp thoại, trừ
769khi danh sách sử dụng nút chọn một hoặc hộp kiểm. Nếu không, bạn có thể bỏ thủ công hộp thoại của mình
770bằng cách gọi {@link android.support.v4.app.DialogFragment#dismiss()} trên {@link
771android.support.v4.app.DialogFragment} của bạn.</p>
772
773<p>Trong trường hợp bạn cần thực hiện các
774hành động nhất định khi hộp thoại biến mất, bạn có thể triển khai phương pháp {@link
775android.support.v4.app.DialogFragment#onDismiss onDismiss()} trong {@link
776android.support.v4.app.DialogFragment} của mình.</p>
777
778<p>Bạn cũng có thể <em>hủy bỏ</em> một hộp thoại. Đây là một sự kiện đặc biệt chỉ báo người dùng
779chủ ý rời khỏi hộp thoại mà không hoàn thành tác vụ. Điều này xảy ra nếu người dùng nhấn nút
780<em>Quay lại</em>, chạm vào màn hình ngoài vùng hộp thoại,
781hoặc nếu bạn công khai gọi {@link android.app.Dialog#cancel()} trên {@link
782android.app.Dialog} (chẳng hạn như khi hồi đáp lại một nút "Hủy bỏ" trong hộp thoại).</p>
783
784<p>Như nêu trong ví dụ bên trên, bạn có thể hồi đáp lại sự kiện hủy bỏ này bằng cách triển khai
785{@link android.support.v4.app.DialogFragment#onCancel onCancel()} trong lớp {@link
786android.support.v4.app.DialogFragment} của mình.</p>
787
788<p class="note"><strong>Lưu ý:</strong> Hệ thống sẽ gọi
789{@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} trên mỗi sự kiện mà
790gọi ra lệnh gọi lại {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Tuy nhiên,
791nếu bạn gọi {@link android.app.Dialog#dismiss Dialog.dismiss()} hoặc {@link
792android.support.v4.app.DialogFragment#dismiss DialogFragment.dismiss()},
793hệ thống sẽ gọi {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} <em>chứ
794không phải</em> {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Vì thế, nhìn chung bạn nên
795gọi {@link android.support.v4.app.DialogFragment#dismiss dismiss()} khi người dùng nhấn nút
796<em>tích cực</em> trong hộp thoại của bạn để xóa hộp thoại khỏi dạng xem.</p>
797
798
799