blob: b3d99c5242f0e0d6ff868e202055c4eeed09e0c1 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
Adam Powelldec9dfd2010-08-09 15:27:54 -070019import com.android.internal.app.ActionBarImpl;
svetoslavganov75986cf2009-05-14 22:28:01 -070020import com.android.internal.policy.PolicyManager;
21
Karl Rosaen53d24af2009-07-14 14:58:10 -070022import android.content.ComponentName;
Adam Powell6e346362010-07-23 10:18:23 -070023import android.content.Context;
Karl Rosaen7bafed82009-09-04 11:15:21 -070024import android.content.ContextWrapper;
Adam Powell6e346362010-07-23 10:18:23 -070025import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.graphics.drawable.Drawable;
27import android.net.Uri;
svetoslavganov75986cf2009-05-14 22:28:01 -070028import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.os.Handler;
Svetoslav Ganov44bfdd82012-01-26 10:00:18 -080030import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.Message;
Adam Powell89fc3ac2011-11-01 18:00:44 -070032import android.util.Log;
Adam Powell2fbf4de62010-09-30 15:46:46 -070033import android.util.TypedValue;
Adam Powelldec9dfd2010-08-09 15:27:54 -070034import android.view.ActionMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.view.ContextMenu;
Adam Powell6e346362010-07-23 10:18:23 -070036import android.view.ContextMenu.ContextMenuInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.view.ContextThemeWrapper;
38import android.view.Gravity;
39import android.view.KeyEvent;
svetoslavganov75986cf2009-05-14 22:28:01 -070040import android.view.LayoutInflater;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.view.Menu;
42import android.view.MenuItem;
43import android.view.MotionEvent;
44import android.view.View;
Adam Powell6e346362010-07-23 10:18:23 -070045import android.view.View.OnCreateContextMenuListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.view.ViewGroup;
Adam Powell6e346362010-07-23 10:18:23 -070047import android.view.ViewGroup.LayoutParams;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.view.Window;
49import android.view.WindowManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070050import android.view.accessibility.AccessibilityEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051
52import java.lang.ref.WeakReference;
53
54/**
55 * Base class for Dialogs.
56 *
57 * <p>Note: Activities provide a facility to manage the creation, saving and
58 * restoring of dialogs. See {@link Activity#onCreateDialog(int)},
59 * {@link Activity#onPrepareDialog(int, Dialog)},
60 * {@link Activity#showDialog(int)}, and {@link Activity#dismissDialog(int)}. If
61 * these methods are used, {@link #getOwnerActivity()} will return the Activity
62 * that managed this dialog.
63 *
64 * <p>Often you will want to have a Dialog display on top of the current
65 * input method, because there is no reason for it to accept text. You can
66 * do this by setting the {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
67 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} window flag (assuming
68 * your Dialog takes input focus, as it the default) with the following code:
69 *
70 * <pre>
Joe Fernandez558459f2011-10-13 16:47:36 -070071 * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
72 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);</pre>
73 *
74 * <div class="special reference">
75 * <h3>Developer Guides</h3>
76 * <p>For more information about creating dialogs, read the
77 * <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a> developer guide.</p>
78 * </div>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 */
80public class Dialog implements DialogInterface, Window.Callback,
81 KeyEvent.Callback, OnCreateContextMenuListener {
Adam Powell89fc3ac2011-11-01 18:00:44 -070082 private static final String TAG = "Dialog";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 private Activity mOwnerActivity;
84
85 final Context mContext;
86 final WindowManager mWindowManager;
87 Window mWindow;
88 View mDecor;
Adam Powelldec9dfd2010-08-09 15:27:54 -070089 private ActionBarImpl mActionBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 /**
91 * This field should be made private, so it is hidden from the SDK.
92 * {@hide}
93 */
94 protected boolean mCancelable = true;
svetoslavganov75986cf2009-05-14 22:28:01 -070095
Dianne Hackbornf812fee2011-01-25 14:54:29 -080096 private String mCancelAndDismissTaken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 private Message mCancelMessage;
98 private Message mDismissMessage;
Romain Guy045163a2009-07-14 13:59:33 -070099 private Message mShowMessage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 private OnKeyListener mOnKeyListener;
102
103 private boolean mCreated = false;
104 private boolean mShowing = false;
Dianne Hackborn8b4cac12011-01-03 13:58:14 -0800105 private boolean mCanceled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 private final Handler mHandler = new Handler();
108
Romain Guy7883c972010-03-01 16:39:17 -0800109 private static final int DISMISS = 0x43;
110 private static final int CANCEL = 0x44;
111 private static final int SHOW = 0x45;
112
113 private Handler mListenersHandler;
114
Adam Powellcfe9aee2011-11-01 14:56:27 -0700115 private ActionMode mActionMode;
116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 private final Runnable mDismissAction = new Runnable() {
118 public void run() {
119 dismissDialog();
120 }
121 };
122
123 /**
124 * Create a Dialog window that uses the default dialog frame style.
125 *
126 * @param context The Context the Dialog is to run it. In particular, it
127 * uses the window manager and theme in this context to
128 * present its UI.
129 */
130 public Dialog(Context context) {
Dianne Hackborne79b5542011-01-27 15:18:46 -0800131 this(context, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 }
133
134 /**
135 * Create a Dialog window that uses a custom dialog style.
136 *
137 * @param context The Context in which the Dialog should run. In particular, it
138 * uses the window manager and theme from this context to
139 * present its UI.
140 * @param theme A style resource describing the theme to use for the
141 * window. See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Style
142 * and Theme Resources</a> for more information about defining and using
143 * styles. This theme is applied on top of the current theme in
144 * <var>context</var>. If 0, the default dialog theme will be used.
145 */
146 public Dialog(Context context, int theme) {
Dianne Hackborne79b5542011-01-27 15:18:46 -0800147 this(context, theme, true);
148 }
149
Jeff Browna492c3a2012-08-23 19:48:44 -0700150 Dialog(Context context, int theme, boolean createContextThemeWrapper) {
151 if (createContextThemeWrapper) {
152 if (theme == 0) {
153 TypedValue outValue = new TypedValue();
154 context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
155 outValue, true);
156 theme = outValue.resourceId;
157 }
158 mContext = new ContextThemeWrapper(context, theme);
159 } else {
160 mContext = context;
Adam Powell2fbf4de62010-09-30 15:46:46 -0700161 }
162
Christian Mehlmaueref367522010-05-31 23:08:30 +0200163 mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 Window w = PolicyManager.makeNewWindow(mContext);
165 mWindow = w;
166 w.setCallback(this);
167 w.setWindowManager(mWindowManager, null, null);
168 w.setGravity(Gravity.CENTER);
Romain Guy045163a2009-07-14 13:59:33 -0700169 mListenersHandler = new ListenersHandler(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 }
Jeff Browna492c3a2012-08-23 19:48:44 -0700171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 /**
173 * @deprecated
174 * @hide
175 */
176 @Deprecated
177 protected Dialog(Context context, boolean cancelable,
178 Message cancelCallback) {
179 this(context);
180 mCancelable = cancelable;
181 mCancelMessage = cancelCallback;
182 }
183
184 protected Dialog(Context context, boolean cancelable,
185 OnCancelListener cancelListener) {
186 this(context);
187 mCancelable = cancelable;
188 setOnCancelListener(cancelListener);
189 }
190
191 /**
192 * Retrieve the Context this Dialog is running in.
193 *
Adam Powellc49c1732010-09-28 16:03:15 -0700194 * @return Context The Context used by the Dialog.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 */
196 public final Context getContext() {
197 return mContext;
198 }
199
200 /**
Adam Powelldec9dfd2010-08-09 15:27:54 -0700201 * Retrieve the {@link ActionBar} attached to this dialog, if present.
202 *
203 * @return The ActionBar attached to the dialog or null if no ActionBar is present.
204 */
205 public ActionBar getActionBar() {
206 return mActionBar;
207 }
208
209 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 * Sets the Activity that owns this dialog. An example use: This Dialog will
211 * use the suggested volume control stream of the Activity.
212 *
213 * @param activity The Activity that owns this dialog.
214 */
215 public final void setOwnerActivity(Activity activity) {
216 mOwnerActivity = activity;
217
218 getWindow().setVolumeControlStream(mOwnerActivity.getVolumeControlStream());
219 }
220
221 /**
222 * Returns the Activity that owns this Dialog. For example, if
223 * {@link Activity#showDialog(int)} is used to show this Dialog, that
224 * Activity will be the owner (by default). Depending on how this dialog was
225 * created, this may return null.
226 *
227 * @return The Activity that owns this Dialog.
228 */
229 public final Activity getOwnerActivity() {
230 return mOwnerActivity;
231 }
232
233 /**
234 * @return Whether the dialog is currently showing.
235 */
236 public boolean isShowing() {
237 return mShowing;
238 }
239
240 /**
241 * Start the dialog and display it on screen. The window is placed in the
242 * application layer and opaque. Note that you should not override this
243 * method to do initialization when the dialog is shown, instead implement
244 * that in {@link #onStart}.
245 */
246 public void show() {
247 if (mShowing) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700248 if (mDecor != null) {
Adam Powelle67a9dc2010-08-17 17:28:56 -0700249 if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
250 mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
251 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700252 mDecor.setVisibility(View.VISIBLE);
253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 return;
255 }
256
Dianne Hackborn8b4cac12011-01-03 13:58:14 -0800257 mCanceled = false;
258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 if (!mCreated) {
260 dispatchOnCreate(null);
261 }
262
263 onStart();
264 mDecor = mWindow.getDecorView();
Adam Powelldec9dfd2010-08-09 15:27:54 -0700265
266 if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
267 mActionBar = new ActionBarImpl(this);
268 }
269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 WindowManager.LayoutParams l = mWindow.getAttributes();
271 if ((l.softInputMode
272 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
273 WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
274 nl.copyFrom(l);
275 nl.softInputMode |=
276 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
277 l = nl;
278 }
Romain Guy045163a2009-07-14 13:59:33 -0700279
Romain Guy7eec2bc2010-03-29 13:00:07 -0700280 try {
281 mWindowManager.addView(mDecor, l);
282 mShowing = true;
283
284 sendShowMessage();
285 } finally {
286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 }
288
289 /**
290 * Hide the dialog, but do not dismiss it.
291 */
292 public void hide() {
svetoslavganov75986cf2009-05-14 22:28:01 -0700293 if (mDecor != null) {
294 mDecor.setVisibility(View.GONE);
295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 }
297
298 /**
299 * Dismiss this dialog, removing it from the screen. This method can be
300 * invoked safely from any thread. Note that you should not override this
301 * method to do cleanup when the dialog is dismissed, instead implement
302 * that in {@link #onStop}.
303 */
304 public void dismiss() {
Svetoslav Ganov44bfdd82012-01-26 10:00:18 -0800305 if (Looper.myLooper() == mHandler.getLooper()) {
306 dismissDialog();
307 } else {
308 mHandler.post(mDismissAction);
309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 }
311
Adam Powell89fc3ac2011-11-01 18:00:44 -0700312 void dismissDialog() {
Romain Guy08a4ac32010-03-16 11:40:40 -0700313 if (mDecor == null || !mShowing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 return;
315 }
316
Adam Powell89fc3ac2011-11-01 18:00:44 -0700317 if (mWindow.isDestroyed()) {
318 Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
319 return;
320 }
321
Romain Guyd2671e12010-03-11 18:06:42 -0800322 try {
323 mWindowManager.removeView(mDecor);
324 } finally {
Adam Powellcfe9aee2011-11-01 14:56:27 -0700325 if (mActionMode != null) {
326 mActionMode.finish();
327 }
Romain Guyd2671e12010-03-11 18:06:42 -0800328 mDecor = null;
329 mWindow.closeAllPanels();
330 onStop();
331 mShowing = false;
332
333 sendDismissMessage();
334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 }
336
337 private void sendDismissMessage() {
338 if (mDismissMessage != null) {
339 // Obtain a new message so this dialog can be re-used
340 Message.obtain(mDismissMessage).sendToTarget();
341 }
342 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700343
Romain Guy045163a2009-07-14 13:59:33 -0700344 private void sendShowMessage() {
345 if (mShowMessage != null) {
346 // Obtain a new message so this dialog can be re-used
347 Message.obtain(mShowMessage).sendToTarget();
348 }
349 }
350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 // internal method to make sure mcreated is set properly without requiring
352 // users to call through to super in onCreate
353 void dispatchOnCreate(Bundle savedInstanceState) {
Romain Guy6de4aed2009-07-08 10:54:45 -0700354 if (!mCreated) {
355 onCreate(savedInstanceState);
356 mCreated = true;
357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 }
359
360 /**
Chet Haase49afa5b2010-08-23 11:39:53 -0700361 * Similar to {@link Activity#onCreate}, you should initialize your dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 * in this method, including calling {@link #setContentView}.
363 * @param savedInstanceState If this dialog is being reinitalized after a
364 * the hosting activity was previously shut down, holds the result from
365 * the most recent call to {@link #onSaveInstanceState}, or null if this
366 * is the first time.
367 */
368 protected void onCreate(Bundle savedInstanceState) {
369 }
370
371 /**
372 * Called when the dialog is starting.
373 */
374 protected void onStart() {
Adam Powell50efbed2011-02-08 16:20:15 -0800375 if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 }
377
378 /**
379 * Called to tell you that you're stopping.
380 */
381 protected void onStop() {
Adam Powell50efbed2011-02-08 16:20:15 -0800382 if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 }
384
385 private static final String DIALOG_SHOWING_TAG = "android:dialogShowing";
386 private static final String DIALOG_HIERARCHY_TAG = "android:dialogHierarchy";
387
388 /**
389 * Saves the state of the dialog into a bundle.
390 *
391 * The default implementation saves the state of its view hierarchy, so you'll
392 * likely want to call through to super if you override this to save additional
393 * state.
394 * @return A bundle with the state of the dialog.
395 */
396 public Bundle onSaveInstanceState() {
397 Bundle bundle = new Bundle();
398 bundle.putBoolean(DIALOG_SHOWING_TAG, mShowing);
399 if (mCreated) {
400 bundle.putBundle(DIALOG_HIERARCHY_TAG, mWindow.saveHierarchyState());
401 }
402 return bundle;
403 }
404
405 /**
406 * Restore the state of the dialog from a previously saved bundle.
407 *
408 * The default implementation restores the state of the dialog's view
409 * hierarchy that was saved in the default implementation of {@link #onSaveInstanceState()},
410 * so be sure to call through to super when overriding unless you want to
411 * do all restoring of state yourself.
412 * @param savedInstanceState The state of the dialog previously saved by
413 * {@link #onSaveInstanceState()}.
414 */
415 public void onRestoreInstanceState(Bundle savedInstanceState) {
416 final Bundle dialogHierarchyState = savedInstanceState.getBundle(DIALOG_HIERARCHY_TAG);
417 if (dialogHierarchyState == null) {
418 // dialog has never been shown, or onCreated, nothing to restore.
419 return;
420 }
421 dispatchOnCreate(savedInstanceState);
422 mWindow.restoreHierarchyState(dialogHierarchyState);
423 if (savedInstanceState.getBoolean(DIALOG_SHOWING_TAG)) {
424 show();
425 }
426 }
427
428 /**
429 * Retrieve the current Window for the activity. This can be used to
430 * directly access parts of the Window API that are not available
431 * through Activity/Screen.
432 *
433 * @return Window The current window, or null if the activity is not
434 * visual.
435 */
436 public Window getWindow() {
437 return mWindow;
438 }
439
440 /**
441 * Call {@link android.view.Window#getCurrentFocus} on the
442 * Window if this Activity to return the currently focused view.
443 *
444 * @return View The current View with focus or null.
445 *
446 * @see #getWindow
447 * @see android.view.Window#getCurrentFocus
448 */
449 public View getCurrentFocus() {
450 return mWindow != null ? mWindow.getCurrentFocus() : null;
451 }
452
453 /**
454 * Finds a view that was identified by the id attribute from the XML that
455 * was processed in {@link #onStart}.
456 *
457 * @param id the identifier of the view to find
458 * @return The view if found or null otherwise.
459 */
460 public View findViewById(int id) {
461 return mWindow.findViewById(id);
462 }
463
464 /**
465 * Set the screen content from a layout resource. The resource will be
466 * inflated, adding all top-level views to the screen.
467 *
468 * @param layoutResID Resource ID to be inflated.
469 */
470 public void setContentView(int layoutResID) {
471 mWindow.setContentView(layoutResID);
472 }
473
474 /**
475 * Set the screen content to an explicit view. This view is placed
476 * directly into the screen's view hierarchy. It can itself be a complex
477 * view hierarhcy.
478 *
479 * @param view The desired content to display.
480 */
481 public void setContentView(View view) {
482 mWindow.setContentView(view);
483 }
484
485 /**
486 * Set the screen content to an explicit view. This view is placed
487 * directly into the screen's view hierarchy. It can itself be a complex
488 * view hierarhcy.
489 *
490 * @param view The desired content to display.
491 * @param params Layout parameters for the view.
492 */
493 public void setContentView(View view, ViewGroup.LayoutParams params) {
494 mWindow.setContentView(view, params);
495 }
496
497 /**
498 * Add an additional content view to the screen. Added after any existing
499 * ones in the screen -- existing views are NOT removed.
500 *
501 * @param view The desired content to display.
502 * @param params Layout parameters for the view.
503 */
504 public void addContentView(View view, ViewGroup.LayoutParams params) {
505 mWindow.addContentView(view, params);
506 }
507
508 /**
509 * Set the title text for this dialog's window.
510 *
511 * @param title The new text to display in the title.
512 */
513 public void setTitle(CharSequence title) {
514 mWindow.setTitle(title);
515 mWindow.getAttributes().setTitle(title);
516 }
517
518 /**
519 * Set the title text for this dialog's window. The text is retrieved
520 * from the resources with the supplied identifier.
521 *
522 * @param titleId the title's text resource identifier
523 */
524 public void setTitle(int titleId) {
525 setTitle(mContext.getText(titleId));
526 }
527
528 /**
529 * A key was pressed down.
530 *
531 * <p>If the focused view didn't want this event, this method is called.
532 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700533 * <p>The default implementation consumed the KEYCODE_BACK to later
534 * handle it in {@link #onKeyUp}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 *
536 * @see #onKeyUp
537 * @see android.view.KeyEvent
538 */
539 public boolean onKeyDown(int keyCode, KeyEvent event) {
540 if (keyCode == KeyEvent.KEYCODE_BACK) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700541 event.startTracking();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 return true;
543 }
544
545 return false;
546 }
547
548 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700549 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
550 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
551 * the event).
552 */
553 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
554 return false;
555 }
556
557 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 * A key was released.
559 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700560 * <p>The default implementation handles KEYCODE_BACK to close the
561 * dialog.
562 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 * @see #onKeyDown
564 * @see KeyEvent
565 */
566 public boolean onKeyUp(int keyCode, KeyEvent event) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700567 if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
568 && !event.isCanceled()) {
569 onBackPressed();
570 return true;
571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 return false;
573 }
574
575 /**
576 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
577 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
578 * the event).
579 */
580 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
581 return false;
582 }
583
584 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700585 * Called when the dialog has detected the user's press of the back
586 * key. The default implementation simply cancels the dialog (only if
587 * it is cancelable), but you can override this to do whatever you want.
588 */
589 public void onBackPressed() {
590 if (mCancelable) {
591 cancel();
592 }
593 }
Jeff Brown64da12a2011-01-04 19:57:47 -0800594
595 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +0900596 * Called when a key shortcut event is not handled by any of the views in the Dialog.
Jeff Brown64da12a2011-01-04 19:57:47 -0800597 * Override this method to implement global key shortcuts for the Dialog.
598 * Key shortcuts can also be implemented by setting the
599 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
600 *
601 * @param keyCode The value in event.getKeyCode().
602 * @param event Description of the key event.
603 * @return True if the key shortcut was handled.
604 */
605 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
606 return false;
607 }
608
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700609 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 * Called when a touch screen event was not handled by any of the views
611 * under it. This is most useful to process touch events that happen outside
612 * of your window bounds, where there is no view to receive it.
613 *
614 * @param event The touch screen event being processed.
615 * @return Return true if you have consumed the event, false if you haven't.
616 * The default implementation will cancel the dialog when a touch
617 * happens outside of the window bounds.
618 */
619 public boolean onTouchEvent(MotionEvent event) {
Dianne Hackborncfaf8872011-01-18 13:57:54 -0800620 if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 cancel();
622 return true;
623 }
624
625 return false;
626 }
627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 /**
629 * Called when the trackball was moved and not handled by any of the
630 * views inside of the activity. So, for example, if the trackball moves
631 * while focus is on a button, you will receive a call here because
632 * buttons do not normally do anything with trackball events. The call
633 * here happens <em>before</em> trackball movements are converted to
634 * DPAD key events, which then get sent back to the view hierarchy, and
635 * will be processed at the point for things like focus navigation.
636 *
637 * @param event The trackball event being processed.
638 *
639 * @return Return true if you have consumed the event, false if you haven't.
640 * The default implementation always returns false.
641 */
642 public boolean onTrackballEvent(MotionEvent event) {
643 return false;
644 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800645
646 /**
647 * Called when a generic motion event was not handled by any of the
648 * views inside of the dialog.
649 * <p>
Jeff Brown33bbfd22011-02-24 20:55:35 -0800650 * Generic motion events describe joystick movements, mouse hovers, track pad
651 * touches, scroll wheel movements and other input events. The
Jeff Browncb1404e2011-01-15 18:14:15 -0800652 * {@link MotionEvent#getSource() source} of the motion event specifies
653 * the class of input that was received. Implementations of this method
654 * must examine the bits in the source before processing the event.
655 * The following code example shows how this is done.
Jeff Brown33bbfd22011-02-24 20:55:35 -0800656 * </p><p>
657 * Generic motion events with source class
658 * {@link android.view.InputDevice#SOURCE_CLASS_POINTER}
659 * are delivered to the view under the pointer. All other generic motion events are
660 * delivered to the focused view.
661 * </p><p>
662 * See {@link View#onGenericMotionEvent(MotionEvent)} for an example of how to
663 * handle this event.
Jeff Browncb1404e2011-01-15 18:14:15 -0800664 * </p>
Jeff Browncb1404e2011-01-15 18:14:15 -0800665 *
666 * @param event The generic motion event being processed.
667 *
668 * @return Return true if you have consumed the event, false if you haven't.
669 * The default implementation always returns false.
670 */
671 public boolean onGenericMotionEvent(MotionEvent event) {
672 return false;
673 }
674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
676 if (mDecor != null) {
677 mWindowManager.updateViewLayout(mDecor, params);
678 }
679 }
680
681 public void onContentChanged() {
682 }
683
684 public void onWindowFocusChanged(boolean hasFocus) {
685 }
686
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700687 public void onAttachedToWindow() {
688 }
689
690 public void onDetachedFromWindow() {
691 }
692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 /**
694 * Called to process key events. You can override this to intercept all
695 * key events before they are dispatched to the window. Be sure to call
696 * this implementation for key events that should be handled normally.
697 *
698 * @param event The key event.
699 *
700 * @return boolean Return true if this event was consumed.
701 */
702 public boolean dispatchKeyEvent(KeyEvent event) {
703 if ((mOnKeyListener != null) && (mOnKeyListener.onKey(this, event.getKeyCode(), event))) {
704 return true;
705 }
706 if (mWindow.superDispatchKeyEvent(event)) {
707 return true;
708 }
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700709 return event.dispatch(this, mDecor != null
710 ? mDecor.getKeyDispatcherState() : null, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 }
712
713 /**
Jeff Brown64da12a2011-01-04 19:57:47 -0800714 * Called to process a key shortcut event.
715 * You can override this to intercept all key shortcut events before they are
716 * dispatched to the window. Be sure to call this implementation for key shortcut
717 * events that should be handled normally.
718 *
719 * @param event The key shortcut event.
720 * @return True if this event was consumed.
721 */
722 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
723 if (mWindow.superDispatchKeyShortcutEvent(event)) {
724 return true;
725 }
726 return onKeyShortcut(event.getKeyCode(), event);
727 }
728
729 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 * Called to process touch screen events. You can override this to
731 * intercept all touch screen events before they are dispatched to the
732 * window. Be sure to call this implementation for touch screen events
733 * that should be handled normally.
734 *
735 * @param ev The touch screen event.
736 *
737 * @return boolean Return true if this event was consumed.
738 */
739 public boolean dispatchTouchEvent(MotionEvent ev) {
740 if (mWindow.superDispatchTouchEvent(ev)) {
741 return true;
742 }
743 return onTouchEvent(ev);
744 }
745
746 /**
747 * Called to process trackball events. You can override this to
748 * intercept all trackball events before they are dispatched to the
749 * window. Be sure to call this implementation for trackball events
750 * that should be handled normally.
751 *
752 * @param ev The trackball event.
753 *
754 * @return boolean Return true if this event was consumed.
755 */
756 public boolean dispatchTrackballEvent(MotionEvent ev) {
757 if (mWindow.superDispatchTrackballEvent(ev)) {
758 return true;
759 }
760 return onTrackballEvent(ev);
761 }
762
Jeff Browncb1404e2011-01-15 18:14:15 -0800763 /**
764 * Called to process generic motion events. You can override this to
765 * intercept all generic motion events before they are dispatched to the
766 * window. Be sure to call this implementation for generic motion events
767 * that should be handled normally.
768 *
769 * @param ev The generic motion event.
770 *
771 * @return boolean Return true if this event was consumed.
772 */
773 public boolean dispatchGenericMotionEvent(MotionEvent ev) {
774 if (mWindow.superDispatchGenericMotionEvent(ev)) {
775 return true;
776 }
777 return onGenericMotionEvent(ev);
778 }
779
svetoslavganov75986cf2009-05-14 22:28:01 -0700780 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
781 event.setClassName(getClass().getName());
782 event.setPackageName(mContext.getPackageName());
783
784 LayoutParams params = getWindow().getAttributes();
Romain Guy980a9382010-01-08 15:06:28 -0800785 boolean isFullScreen = (params.width == LayoutParams.MATCH_PARENT) &&
786 (params.height == LayoutParams.MATCH_PARENT);
svetoslavganov75986cf2009-05-14 22:28:01 -0700787 event.setFullScreen(isFullScreen);
788
789 return false;
790 }
791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 /**
793 * @see Activity#onCreatePanelView(int)
794 */
795 public View onCreatePanelView(int featureId) {
796 return null;
797 }
798
799 /**
800 * @see Activity#onCreatePanelMenu(int, Menu)
801 */
802 public boolean onCreatePanelMenu(int featureId, Menu menu) {
803 if (featureId == Window.FEATURE_OPTIONS_PANEL) {
804 return onCreateOptionsMenu(menu);
805 }
806
807 return false;
808 }
809
810 /**
811 * @see Activity#onPreparePanel(int, View, Menu)
812 */
813 public boolean onPreparePanel(int featureId, View view, Menu menu) {
814 if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
815 boolean goforit = onPrepareOptionsMenu(menu);
816 return goforit && menu.hasVisibleItems();
817 }
818 return true;
819 }
820
821 /**
822 * @see Activity#onMenuOpened(int, Menu)
823 */
824 public boolean onMenuOpened(int featureId, Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800825 if (featureId == Window.FEATURE_ACTION_BAR) {
826 mActionBar.dispatchMenuVisibilityChanged(true);
827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 return true;
829 }
830
831 /**
832 * @see Activity#onMenuItemSelected(int, MenuItem)
833 */
834 public boolean onMenuItemSelected(int featureId, MenuItem item) {
835 return false;
836 }
837
838 /**
839 * @see Activity#onPanelClosed(int, Menu)
840 */
841 public void onPanelClosed(int featureId, Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800842 if (featureId == Window.FEATURE_ACTION_BAR) {
843 mActionBar.dispatchMenuVisibilityChanged(false);
844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 }
846
847 /**
848 * It is usually safe to proxy this call to the owner activity's
849 * {@link Activity#onCreateOptionsMenu(Menu)} if the client desires the same
850 * menu for this Dialog.
851 *
852 * @see Activity#onCreateOptionsMenu(Menu)
853 * @see #getOwnerActivity()
854 */
855 public boolean onCreateOptionsMenu(Menu menu) {
856 return true;
857 }
858
859 /**
860 * It is usually safe to proxy this call to the owner activity's
861 * {@link Activity#onPrepareOptionsMenu(Menu)} if the client desires the
862 * same menu for this Dialog.
863 *
864 * @see Activity#onPrepareOptionsMenu(Menu)
865 * @see #getOwnerActivity()
866 */
867 public boolean onPrepareOptionsMenu(Menu menu) {
868 return true;
869 }
870
871 /**
872 * @see Activity#onOptionsItemSelected(MenuItem)
873 */
874 public boolean onOptionsItemSelected(MenuItem item) {
875 return false;
876 }
877
878 /**
879 * @see Activity#onOptionsMenuClosed(Menu)
880 */
881 public void onOptionsMenuClosed(Menu menu) {
882 }
883
884 /**
885 * @see Activity#openOptionsMenu()
886 */
887 public void openOptionsMenu() {
888 mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
889 }
890
891 /**
892 * @see Activity#closeOptionsMenu()
893 */
894 public void closeOptionsMenu() {
895 mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
896 }
897
898 /**
Adam Powelle67a9dc2010-08-17 17:28:56 -0700899 * @see Activity#invalidateOptionsMenu()
900 */
901 public void invalidateOptionsMenu() {
902 mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
903 }
904
905 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 * @see Activity#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)
907 */
908 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
909 }
910
911 /**
912 * @see Activity#registerForContextMenu(View)
913 */
914 public void registerForContextMenu(View view) {
915 view.setOnCreateContextMenuListener(this);
916 }
917
918 /**
919 * @see Activity#unregisterForContextMenu(View)
920 */
921 public void unregisterForContextMenu(View view) {
922 view.setOnCreateContextMenuListener(null);
923 }
924
925 /**
926 * @see Activity#openContextMenu(View)
927 */
928 public void openContextMenu(View view) {
929 view.showContextMenu();
930 }
931
932 /**
933 * @see Activity#onContextItemSelected(MenuItem)
934 */
935 public boolean onContextItemSelected(MenuItem item) {
936 return false;
937 }
938
939 /**
940 * @see Activity#onContextMenuClosed(Menu)
941 */
942 public void onContextMenuClosed(Menu menu) {
943 }
944
945 /**
946 * This hook is called when the user signals the desire to start a search.
947 */
948 public boolean onSearchRequested() {
Karl Rosaen53d24af2009-07-14 14:58:10 -0700949 final SearchManager searchManager = (SearchManager) mContext
950 .getSystemService(Context.SEARCH_SERVICE);
951
Bjorn Bringertb8144a92010-02-22 20:48:57 +0000952 // associate search with owner activity
Karl Rosaen7bafed82009-09-04 11:15:21 -0700953 final ComponentName appName = getAssociatedActivity();
lge-aosp06ca9972011-03-15 10:25:57 +0900954 if (appName != null && searchManager.getSearchableInfo(appName) != null) {
Bjorn Bringertb8144a92010-02-22 20:48:57 +0000955 searchManager.startSearch(null, false, appName, null, false);
956 dismiss();
957 return true;
958 } else {
959 return false;
960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 }
962
Adam Powelldebf3be2010-11-15 18:58:48 -0800963 public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700964 if (mActionBar != null) {
965 return mActionBar.startActionMode(callback);
966 }
Adam Powell6e346362010-07-23 10:18:23 -0700967 return null;
968 }
969
Adam Powellcfe9aee2011-11-01 14:56:27 -0700970 /**
971 * {@inheritDoc}
972 *
973 * Note that if you override this method you should always call through
974 * to the superclass implementation by calling super.onActionModeStarted(mode).
975 */
Adam Powelldebf3be2010-11-15 18:58:48 -0800976 public void onActionModeStarted(ActionMode mode) {
Adam Powellcfe9aee2011-11-01 14:56:27 -0700977 mActionMode = mode;
Adam Powelldebf3be2010-11-15 18:58:48 -0800978 }
979
Adam Powellcfe9aee2011-11-01 14:56:27 -0700980 /**
981 * {@inheritDoc}
982 *
983 * Note that if you override this method you should always call through
984 * to the superclass implementation by calling super.onActionModeFinished(mode).
985 */
Adam Powelldebf3be2010-11-15 18:58:48 -0800986 public void onActionModeFinished(ActionMode mode) {
Adam Powellcfe9aee2011-11-01 14:56:27 -0700987 if (mode == mActionMode) {
988 mActionMode = null;
989 }
Adam Powelldebf3be2010-11-15 18:58:48 -0800990 }
991
Karl Rosaen7bafed82009-09-04 11:15:21 -0700992 /**
Adam Powelldec9dfd2010-08-09 15:27:54 -0700993 * @return The activity associated with this dialog, or null if there is no associated activity.
Karl Rosaen7bafed82009-09-04 11:15:21 -0700994 */
995 private ComponentName getAssociatedActivity() {
996 Activity activity = mOwnerActivity;
997 Context context = getContext();
998 while (activity == null && context != null) {
999 if (context instanceof Activity) {
1000 activity = (Activity) context; // found it!
1001 } else {
1002 context = (context instanceof ContextWrapper) ?
1003 ((ContextWrapper) context).getBaseContext() : // unwrap one level
1004 null; // done
1005 }
1006 }
1007 return activity == null ? null : activity.getComponentName();
1008 }
1009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010
1011 /**
1012 * Request that key events come to this dialog. Use this if your
1013 * dialog has no views with focus, but the dialog still wants
1014 * a chance to process key events.
1015 *
1016 * @param get true if the dialog should receive key events, false otherwise
1017 * @see android.view.Window#takeKeyEvents
1018 */
1019 public void takeKeyEvents(boolean get) {
1020 mWindow.takeKeyEvents(get);
1021 }
1022
1023 /**
1024 * Enable extended window features. This is a convenience for calling
1025 * {@link android.view.Window#requestFeature getWindow().requestFeature()}.
1026 *
1027 * @param featureId The desired feature as defined in
1028 * {@link android.view.Window}.
1029 * @return Returns true if the requested feature is supported and now
1030 * enabled.
1031 *
1032 * @see android.view.Window#requestFeature
1033 */
1034 public final boolean requestWindowFeature(int featureId) {
1035 return getWindow().requestFeature(featureId);
1036 }
1037
1038 /**
1039 * Convenience for calling
1040 * {@link android.view.Window#setFeatureDrawableResource}.
1041 */
1042 public final void setFeatureDrawableResource(int featureId, int resId) {
1043 getWindow().setFeatureDrawableResource(featureId, resId);
1044 }
1045
1046 /**
1047 * Convenience for calling
1048 * {@link android.view.Window#setFeatureDrawableUri}.
1049 */
1050 public final void setFeatureDrawableUri(int featureId, Uri uri) {
1051 getWindow().setFeatureDrawableUri(featureId, uri);
1052 }
1053
1054 /**
1055 * Convenience for calling
1056 * {@link android.view.Window#setFeatureDrawable(int, Drawable)}.
1057 */
1058 public final void setFeatureDrawable(int featureId, Drawable drawable) {
1059 getWindow().setFeatureDrawable(featureId, drawable);
1060 }
1061
1062 /**
1063 * Convenience for calling
1064 * {@link android.view.Window#setFeatureDrawableAlpha}.
1065 */
1066 public final void setFeatureDrawableAlpha(int featureId, int alpha) {
1067 getWindow().setFeatureDrawableAlpha(featureId, alpha);
1068 }
1069
1070 public LayoutInflater getLayoutInflater() {
1071 return getWindow().getLayoutInflater();
1072 }
1073
1074 /**
1075 * Sets whether this dialog is cancelable with the
1076 * {@link KeyEvent#KEYCODE_BACK BACK} key.
1077 */
1078 public void setCancelable(boolean flag) {
1079 mCancelable = flag;
1080 }
1081
1082 /**
1083 * Sets whether this dialog is canceled when touched outside the window's
1084 * bounds. If setting to true, the dialog is set to be cancelable if not
1085 * already set.
1086 *
1087 * @param cancel Whether the dialog should be canceled when touched outside
1088 * the window.
1089 */
1090 public void setCanceledOnTouchOutside(boolean cancel) {
1091 if (cancel && !mCancelable) {
1092 mCancelable = true;
1093 }
1094
Dianne Hackborncfaf8872011-01-18 13:57:54 -08001095 mWindow.setCloseOnTouchOutside(cancel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 }
1097
1098 /**
1099 * Cancel the dialog. This is essentially the same as calling {@link #dismiss()}, but it will
1100 * also call your {@link DialogInterface.OnCancelListener} (if registered).
1101 */
1102 public void cancel() {
Dianne Hackborn8b4cac12011-01-03 13:58:14 -08001103 if (!mCanceled && mCancelMessage != null) {
1104 mCanceled = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 // Obtain a new message so this dialog can be re-used
1106 Message.obtain(mCancelMessage).sendToTarget();
1107 }
1108 dismiss();
1109 }
1110
1111 /**
1112 * Set a listener to be invoked when the dialog is canceled.
Adam Powell7f02dc52012-08-27 13:35:16 -07001113 *
1114 * <p>This will only be invoked when the dialog is canceled.
1115 * Cancel events alone will not capture all ways that
1116 * the dialog might be dismissed. If the creator needs
1117 * to know when a dialog is dismissed in general, use
1118 * {@link #setOnDismissListener}.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 *
1120 * @param listener The {@link DialogInterface.OnCancelListener} to use.
1121 */
1122 public void setOnCancelListener(final OnCancelListener listener) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001123 if (mCancelAndDismissTaken != null) {
1124 throw new IllegalStateException(
1125 "OnCancelListener is already taken by "
1126 + mCancelAndDismissTaken + " and can not be replaced.");
1127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 if (listener != null) {
Romain Guy045163a2009-07-14 13:59:33 -07001129 mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 } else {
1131 mCancelMessage = null;
1132 }
1133 }
1134
1135 /**
1136 * Set a message to be sent when the dialog is canceled.
1137 * @param msg The msg to send when the dialog is canceled.
1138 * @see #setOnCancelListener(android.content.DialogInterface.OnCancelListener)
1139 */
1140 public void setCancelMessage(final Message msg) {
1141 mCancelMessage = msg;
1142 }
1143
1144 /**
1145 * Set a listener to be invoked when the dialog is dismissed.
1146 * @param listener The {@link DialogInterface.OnDismissListener} to use.
1147 */
1148 public void setOnDismissListener(final OnDismissListener listener) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001149 if (mCancelAndDismissTaken != null) {
1150 throw new IllegalStateException(
1151 "OnDismissListener is already taken by "
1152 + mCancelAndDismissTaken + " and can not be replaced.");
1153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 if (listener != null) {
Romain Guy045163a2009-07-14 13:59:33 -07001155 mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 } else {
1157 mDismissMessage = null;
1158 }
1159 }
1160
1161 /**
Romain Guy045163a2009-07-14 13:59:33 -07001162 * Sets a listener to be invoked when the dialog is shown.
Ficus Kirkpatrick130a8b72010-01-14 15:39:43 -08001163 * @param listener The {@link DialogInterface.OnShowListener} to use.
Romain Guy045163a2009-07-14 13:59:33 -07001164 */
1165 public void setOnShowListener(OnShowListener listener) {
1166 if (listener != null) {
1167 mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
1168 } else {
1169 mShowMessage = null;
1170 }
1171 }
1172
1173 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 * Set a message to be sent when the dialog is dismissed.
1175 * @param msg The msg to send when the dialog is dismissed.
1176 */
1177 public void setDismissMessage(final Message msg) {
1178 mDismissMessage = msg;
1179 }
1180
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001181 /** @hide */
1182 public boolean takeCancelAndDismissListeners(String msg, final OnCancelListener cancel,
1183 final OnDismissListener dismiss) {
1184 if (mCancelAndDismissTaken != null) {
1185 mCancelAndDismissTaken = null;
1186 } else if (mCancelMessage != null || mDismissMessage != null) {
1187 return false;
1188 }
1189
1190 setOnCancelListener(cancel);
1191 setOnDismissListener(dismiss);
1192 mCancelAndDismissTaken = msg;
1193
1194 return true;
1195 }
1196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 /**
1198 * By default, this will use the owner Activity's suggested stream type.
1199 *
1200 * @see Activity#setVolumeControlStream(int)
1201 * @see #setOwnerActivity(Activity)
1202 */
1203 public final void setVolumeControlStream(int streamType) {
1204 getWindow().setVolumeControlStream(streamType);
1205 }
1206
1207 /**
1208 * @see Activity#getVolumeControlStream()
1209 */
1210 public final int getVolumeControlStream() {
1211 return getWindow().getVolumeControlStream();
1212 }
1213
1214 /**
1215 * Sets the callback that will be called if a key is dispatched to the dialog.
1216 */
1217 public void setOnKeyListener(final OnKeyListener onKeyListener) {
1218 mOnKeyListener = onKeyListener;
1219 }
1220
Romain Guy045163a2009-07-14 13:59:33 -07001221 private static final class ListenersHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 private WeakReference<DialogInterface> mDialog;
1223
Romain Guy045163a2009-07-14 13:59:33 -07001224 public ListenersHandler(Dialog dialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 mDialog = new WeakReference<DialogInterface>(dialog);
1226 }
1227
1228 @Override
1229 public void handleMessage(Message msg) {
1230 switch (msg.what) {
1231 case DISMISS:
1232 ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
1233 break;
1234 case CANCEL:
1235 ((OnCancelListener) msg.obj).onCancel(mDialog.get());
1236 break;
Romain Guy045163a2009-07-14 13:59:33 -07001237 case SHOW:
1238 ((OnShowListener) msg.obj).onShow(mDialog.get());
1239 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 }
1241 }
1242 }
1243}