blob: 79461b4863ef7b83b351c5a2a235a4479a8e27e5 [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
Tor Norbyec615c6f2015-03-02 10:11:44 -080019import android.annotation.CallSuper;
Tor Norbye7b9c9122013-05-30 16:48:33 -070020import android.annotation.DrawableRes;
21import android.annotation.IdRes;
22import android.annotation.LayoutRes;
Alan Viverette682a4332015-04-10 11:05:50 -070023import android.annotation.NonNull;
Scott Kennedyc0519552015-02-11 15:33:10 -080024import android.annotation.Nullable;
Clara Bayarri75e09792015-07-29 16:20:40 +010025import android.annotation.StringRes;
Alan Viverette682a4332015-04-10 11:05:50 -070026import android.annotation.StyleRes;
Karl Rosaen53d24af2009-07-14 14:58:10 -070027import android.content.ComponentName;
Adam Powell6e346362010-07-23 10:18:23 -070028import android.content.Context;
Karl Rosaen7bafed82009-09-04 11:15:21 -070029import android.content.ContextWrapper;
Adam Powell6e346362010-07-23 10:18:23 -070030import android.content.DialogInterface;
Jorim Jaggib10e33f2015-02-04 21:57:40 +010031import android.content.pm.ApplicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.graphics.drawable.Drawable;
33import android.net.Uri;
svetoslavganov75986cf2009-05-14 22:28:01 -070034import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.Handler;
Svetoslav Ganov44bfdd82012-01-26 10:00:18 -080036import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.os.Message;
Adam Powell89fc3ac2011-11-01 18:00:44 -070038import android.util.Log;
Adam Powell2fbf4de62010-09-30 15:46:46 -070039import android.util.TypedValue;
Adam Powelldec9dfd2010-08-09 15:27:54 -070040import android.view.ActionMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.view.ContextMenu;
Adam Powell6e346362010-07-23 10:18:23 -070042import android.view.ContextMenu.ContextMenuInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.view.ContextThemeWrapper;
44import android.view.Gravity;
45import android.view.KeyEvent;
Clara Bayarri75e09792015-07-29 16:20:40 +010046import android.view.KeyboardShortcutGroup;
svetoslavganov75986cf2009-05-14 22:28:01 -070047import android.view.LayoutInflater;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.view.Menu;
49import android.view.MenuItem;
50import android.view.MotionEvent;
Tim Kilbourn6a975b32015-04-09 17:14:34 -070051import android.view.SearchEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.view.View;
Adam Powell6e346362010-07-23 10:18:23 -070053import android.view.View.OnCreateContextMenuListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.view.ViewGroup;
Adam Powell6e346362010-07-23 10:18:23 -070055import android.view.ViewGroup.LayoutParams;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.view.Window;
57import android.view.WindowManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070058import android.view.accessibility.AccessibilityEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059
Alan Viverette5696f042015-04-08 11:03:32 -070060import com.android.internal.R;
61import com.android.internal.app.WindowDecorActionBar;
Clara Bayarri75e09792015-07-29 16:20:40 +010062import com.android.internal.policy.PhoneWindow;
Alan Viverette5696f042015-04-08 11:03:32 -070063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import java.lang.ref.WeakReference;
Clara Bayarri75e09792015-07-29 16:20:40 +010065import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066
67/**
68 * Base class for Dialogs.
69 *
70 * <p>Note: Activities provide a facility to manage the creation, saving and
71 * restoring of dialogs. See {@link Activity#onCreateDialog(int)},
72 * {@link Activity#onPrepareDialog(int, Dialog)},
73 * {@link Activity#showDialog(int)}, and {@link Activity#dismissDialog(int)}. If
74 * these methods are used, {@link #getOwnerActivity()} will return the Activity
75 * that managed this dialog.
76 *
77 * <p>Often you will want to have a Dialog display on top of the current
78 * input method, because there is no reason for it to accept text. You can
79 * do this by setting the {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
80 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} window flag (assuming
81 * your Dialog takes input focus, as it the default) with the following code:
82 *
83 * <pre>
Joe Fernandez558459f2011-10-13 16:47:36 -070084 * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
85 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);</pre>
86 *
87 * <div class="special reference">
88 * <h3>Developer Guides</h3>
89 * <p>For more information about creating dialogs, read the
90 * <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a> developer guide.</p>
91 * </div>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 */
93public class Dialog implements DialogInterface, Window.Callback,
Adam Powell117b6952014-05-05 18:14:56 -070094 KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {
Adam Powell89fc3ac2011-11-01 18:00:44 -070095 private static final String TAG = "Dialog";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 private Activity mOwnerActivity;
97
98 final Context mContext;
99 final WindowManager mWindowManager;
100 Window mWindow;
101 View mDecor;
Adam Powelle43340c2014-03-17 19:10:43 -0700102 private ActionBar mActionBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 /**
104 * This field should be made private, so it is hidden from the SDK.
105 * {@hide}
106 */
107 protected boolean mCancelable = true;
svetoslavganov75986cf2009-05-14 22:28:01 -0700108
Dianne Hackbornf812fee2011-01-25 14:54:29 -0800109 private String mCancelAndDismissTaken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 private Message mCancelMessage;
111 private Message mDismissMessage;
Romain Guy045163a2009-07-14 13:59:33 -0700112 private Message mShowMessage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 private OnKeyListener mOnKeyListener;
115
116 private boolean mCreated = false;
117 private boolean mShowing = false;
Dianne Hackborn8b4cac12011-01-03 13:58:14 -0800118 private boolean mCanceled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 private final Handler mHandler = new Handler();
121
Romain Guy7883c972010-03-01 16:39:17 -0800122 private static final int DISMISS = 0x43;
123 private static final int CANCEL = 0x44;
124 private static final int SHOW = 0x45;
125
126 private Handler mListenersHandler;
127
Tim Kilbourn6a975b32015-04-09 17:14:34 -0700128 private SearchEvent mSearchEvent;
129
Adam Powellcfe9aee2011-11-01 14:56:27 -0700130 private ActionMode mActionMode;
131
Clara Bayarri4423d912015-03-02 19:42:48 +0000132 private int mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 private final Runnable mDismissAction = new Runnable() {
135 public void run() {
136 dismissDialog();
137 }
138 };
139
140 /**
Alan Viverette5696f042015-04-08 11:03:32 -0700141 * Creates a dialog window that uses the default dialog theme.
142 * <p>
143 * The supplied {@code context} is used to obtain the window manager and
144 * base theme used to present the dialog.
145 *
146 * @param context the context in which the dialog should run
147 * @see android.R.styleable#Theme_dialogTheme
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 */
Alan Viverette682a4332015-04-10 11:05:50 -0700149 public Dialog(@NonNull Context context) {
Dianne Hackborne79b5542011-01-27 15:18:46 -0800150 this(context, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 }
152
153 /**
Alan Viverette5696f042015-04-08 11:03:32 -0700154 * Creates a dialog window that uses a custom dialog style.
155 * <p>
156 * The supplied {@code context} is used to obtain the window manager and
157 * base theme used to present the dialog.
158 * <p>
159 * The supplied {@code theme} is applied on top of the context's theme. See
160 * <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">
161 * Style and Theme Resources</a> for more information about defining and
162 * using styles.
Jorim Jaggib10e33f2015-02-04 21:57:40 +0100163 *
Alan Viverette5696f042015-04-08 11:03:32 -0700164 * @param context the context in which the dialog should run
Alan Viverette682a4332015-04-10 11:05:50 -0700165 * @param themeResId a style resource describing the theme to use for the
Alan Viverette5696f042015-04-08 11:03:32 -0700166 * window, or {@code 0} to use the default dialog theme
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 */
Alan Viverette682a4332015-04-10 11:05:50 -0700168 public Dialog(@NonNull Context context, @StyleRes int themeResId) {
169 this(context, themeResId, true);
Dianne Hackborne79b5542011-01-27 15:18:46 -0800170 }
171
Alan Viverette682a4332015-04-10 11:05:50 -0700172 Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
Jeff Browna492c3a2012-08-23 19:48:44 -0700173 if (createContextThemeWrapper) {
Alan Viverette682a4332015-04-10 11:05:50 -0700174 if (themeResId == 0) {
Alan Viverette5696f042015-04-08 11:03:32 -0700175 final TypedValue outValue = new TypedValue();
176 context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
Alan Viverette682a4332015-04-10 11:05:50 -0700177 themeResId = outValue.resourceId;
Jeff Browna492c3a2012-08-23 19:48:44 -0700178 }
Alan Viverette682a4332015-04-10 11:05:50 -0700179 mContext = new ContextThemeWrapper(context, themeResId);
Jeff Browna492c3a2012-08-23 19:48:44 -0700180 } else {
181 mContext = context;
Adam Powell2fbf4de62010-09-30 15:46:46 -0700182 }
183
Alan Viverette682a4332015-04-10 11:05:50 -0700184 mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Alan Viverette5696f042015-04-08 11:03:32 -0700185
186 final Window w = new PhoneWindow(mContext);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 mWindow = w;
188 w.setCallback(this);
Adam Powell117b6952014-05-05 18:14:56 -0700189 w.setOnWindowDismissedCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 w.setWindowManager(mWindowManager, null, null);
191 w.setGravity(Gravity.CENTER);
Alan Viverette5696f042015-04-08 11:03:32 -0700192
Romain Guy045163a2009-07-14 13:59:33 -0700193 mListenersHandler = new ListenersHandler(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 }
Jeff Browna492c3a2012-08-23 19:48:44 -0700195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 /**
197 * @deprecated
198 * @hide
199 */
200 @Deprecated
Alan Viverette682a4332015-04-10 11:05:50 -0700201 protected Dialog(@NonNull Context context, boolean cancelable, Message cancelCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 this(context);
203 mCancelable = cancelable;
204 mCancelMessage = cancelCallback;
205 }
206
Alan Viverette682a4332015-04-10 11:05:50 -0700207 protected Dialog(@NonNull Context context, boolean cancelable,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 OnCancelListener cancelListener) {
209 this(context);
210 mCancelable = cancelable;
211 setOnCancelListener(cancelListener);
212 }
213
214 /**
215 * Retrieve the Context this Dialog is running in.
216 *
Adam Powellc49c1732010-09-28 16:03:15 -0700217 * @return Context The Context used by the Dialog.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 */
Alan Viverette682a4332015-04-10 11:05:50 -0700219 @NonNull
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 public final Context getContext() {
221 return mContext;
222 }
223
224 /**
Adam Powelldec9dfd2010-08-09 15:27:54 -0700225 * Retrieve the {@link ActionBar} attached to this dialog, if present.
226 *
227 * @return The ActionBar attached to the dialog or null if no ActionBar is present.
228 */
229 public ActionBar getActionBar() {
230 return mActionBar;
231 }
232
233 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 * Sets the Activity that owns this dialog. An example use: This Dialog will
235 * use the suggested volume control stream of the Activity.
236 *
237 * @param activity The Activity that owns this dialog.
238 */
239 public final void setOwnerActivity(Activity activity) {
240 mOwnerActivity = activity;
241
242 getWindow().setVolumeControlStream(mOwnerActivity.getVolumeControlStream());
243 }
244
245 /**
246 * Returns the Activity that owns this Dialog. For example, if
247 * {@link Activity#showDialog(int)} is used to show this Dialog, that
248 * Activity will be the owner (by default). Depending on how this dialog was
249 * created, this may return null.
250 *
251 * @return The Activity that owns this Dialog.
252 */
253 public final Activity getOwnerActivity() {
254 return mOwnerActivity;
255 }
256
257 /**
258 * @return Whether the dialog is currently showing.
259 */
260 public boolean isShowing() {
261 return mShowing;
262 }
263
264 /**
Alan Viverettef34ef742013-12-11 15:59:53 -0800265 * Forces immediate creation of the dialog.
266 * <p>
267 * Note that you should not override this method to perform dialog creation.
268 * Rather, override {@link #onCreate(Bundle)}.
269 */
270 public void create() {
271 if (!mCreated) {
272 dispatchOnCreate(null);
273 }
274 }
275
276 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 * Start the dialog and display it on screen. The window is placed in the
278 * application layer and opaque. Note that you should not override this
279 * method to do initialization when the dialog is shown, instead implement
280 * that in {@link #onStart}.
281 */
282 public void show() {
283 if (mShowing) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700284 if (mDecor != null) {
Adam Powelle67a9dc2010-08-17 17:28:56 -0700285 if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
286 mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
287 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700288 mDecor.setVisibility(View.VISIBLE);
289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 return;
291 }
292
Dianne Hackborn8b4cac12011-01-03 13:58:14 -0800293 mCanceled = false;
294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 if (!mCreated) {
296 dispatchOnCreate(null);
297 }
298
299 onStart();
300 mDecor = mWindow.getDecorView();
Adam Powelldec9dfd2010-08-09 15:27:54 -0700301
302 if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
Adam Powell04fe6eb2013-05-31 14:39:48 -0700303 final ApplicationInfo info = mContext.getApplicationInfo();
304 mWindow.setDefaultIcon(info.icon);
305 mWindow.setDefaultLogo(info.logo);
Adam Powelle43340c2014-03-17 19:10:43 -0700306 mActionBar = new WindowDecorActionBar(this);
Adam Powelldec9dfd2010-08-09 15:27:54 -0700307 }
308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 WindowManager.LayoutParams l = mWindow.getAttributes();
310 if ((l.softInputMode
311 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
312 WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
313 nl.copyFrom(l);
314 nl.softInputMode |=
315 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
316 l = nl;
317 }
Romain Guy045163a2009-07-14 13:59:33 -0700318
Romain Guy7eec2bc2010-03-29 13:00:07 -0700319 try {
320 mWindowManager.addView(mDecor, l);
321 mShowing = true;
322
323 sendShowMessage();
324 } finally {
325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 }
327
328 /**
329 * Hide the dialog, but do not dismiss it.
330 */
331 public void hide() {
svetoslavganov75986cf2009-05-14 22:28:01 -0700332 if (mDecor != null) {
333 mDecor.setVisibility(View.GONE);
334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 }
336
337 /**
338 * Dismiss this dialog, removing it from the screen. This method can be
339 * invoked safely from any thread. Note that you should not override this
340 * method to do cleanup when the dialog is dismissed, instead implement
341 * that in {@link #onStop}.
342 */
Craig Mautner92098c72013-06-10 11:27:26 -0700343 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 public void dismiss() {
Svetoslav Ganov44bfdd82012-01-26 10:00:18 -0800345 if (Looper.myLooper() == mHandler.getLooper()) {
346 dismissDialog();
347 } else {
348 mHandler.post(mDismissAction);
349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
351
Adam Powell89fc3ac2011-11-01 18:00:44 -0700352 void dismissDialog() {
Romain Guy08a4ac32010-03-16 11:40:40 -0700353 if (mDecor == null || !mShowing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 return;
355 }
356
Adam Powell89fc3ac2011-11-01 18:00:44 -0700357 if (mWindow.isDestroyed()) {
358 Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
359 return;
360 }
361
Romain Guyd2671e12010-03-11 18:06:42 -0800362 try {
Craig Mautner92098c72013-06-10 11:27:26 -0700363 mWindowManager.removeViewImmediate(mDecor);
Romain Guyd2671e12010-03-11 18:06:42 -0800364 } finally {
Adam Powellcfe9aee2011-11-01 14:56:27 -0700365 if (mActionMode != null) {
366 mActionMode.finish();
367 }
Romain Guyd2671e12010-03-11 18:06:42 -0800368 mDecor = null;
369 mWindow.closeAllPanels();
370 onStop();
371 mShowing = false;
Craig Mautner92098c72013-06-10 11:27:26 -0700372
Romain Guyd2671e12010-03-11 18:06:42 -0800373 sendDismissMessage();
374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 }
376
377 private void sendDismissMessage() {
378 if (mDismissMessage != null) {
379 // Obtain a new message so this dialog can be re-used
380 Message.obtain(mDismissMessage).sendToTarget();
381 }
382 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700383
Romain Guy045163a2009-07-14 13:59:33 -0700384 private void sendShowMessage() {
385 if (mShowMessage != null) {
386 // Obtain a new message so this dialog can be re-used
387 Message.obtain(mShowMessage).sendToTarget();
388 }
389 }
390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 // internal method to make sure mcreated is set properly without requiring
392 // users to call through to super in onCreate
393 void dispatchOnCreate(Bundle savedInstanceState) {
Alan Viverettef34ef742013-12-11 15:59:53 -0800394 if (!mCreated) {
Romain Guy6de4aed2009-07-08 10:54:45 -0700395 onCreate(savedInstanceState);
396 mCreated = true;
397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 }
399
400 /**
Chet Haase49afa5b2010-08-23 11:39:53 -0700401 * Similar to {@link Activity#onCreate}, you should initialize your dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 * in this method, including calling {@link #setContentView}.
403 * @param savedInstanceState If this dialog is being reinitalized after a
404 * the hosting activity was previously shut down, holds the result from
405 * the most recent call to {@link #onSaveInstanceState}, or null if this
406 * is the first time.
407 */
408 protected void onCreate(Bundle savedInstanceState) {
409 }
410
411 /**
412 * Called when the dialog is starting.
413 */
414 protected void onStart() {
Adam Powell50efbed2011-02-08 16:20:15 -0800415 if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 }
417
418 /**
419 * Called to tell you that you're stopping.
420 */
421 protected void onStop() {
Adam Powell50efbed2011-02-08 16:20:15 -0800422 if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 }
424
425 private static final String DIALOG_SHOWING_TAG = "android:dialogShowing";
426 private static final String DIALOG_HIERARCHY_TAG = "android:dialogHierarchy";
427
428 /**
429 * Saves the state of the dialog into a bundle.
430 *
431 * The default implementation saves the state of its view hierarchy, so you'll
432 * likely want to call through to super if you override this to save additional
433 * state.
434 * @return A bundle with the state of the dialog.
435 */
436 public Bundle onSaveInstanceState() {
437 Bundle bundle = new Bundle();
438 bundle.putBoolean(DIALOG_SHOWING_TAG, mShowing);
439 if (mCreated) {
440 bundle.putBundle(DIALOG_HIERARCHY_TAG, mWindow.saveHierarchyState());
441 }
442 return bundle;
443 }
444
445 /**
446 * Restore the state of the dialog from a previously saved bundle.
447 *
448 * The default implementation restores the state of the dialog's view
449 * hierarchy that was saved in the default implementation of {@link #onSaveInstanceState()},
450 * so be sure to call through to super when overriding unless you want to
451 * do all restoring of state yourself.
452 * @param savedInstanceState The state of the dialog previously saved by
453 * {@link #onSaveInstanceState()}.
454 */
455 public void onRestoreInstanceState(Bundle savedInstanceState) {
456 final Bundle dialogHierarchyState = savedInstanceState.getBundle(DIALOG_HIERARCHY_TAG);
457 if (dialogHierarchyState == null) {
458 // dialog has never been shown, or onCreated, nothing to restore.
459 return;
460 }
461 dispatchOnCreate(savedInstanceState);
462 mWindow.restoreHierarchyState(dialogHierarchyState);
463 if (savedInstanceState.getBoolean(DIALOG_SHOWING_TAG)) {
464 show();
465 }
466 }
467
468 /**
469 * Retrieve the current Window for the activity. This can be used to
470 * directly access parts of the Window API that are not available
471 * through Activity/Screen.
472 *
473 * @return Window The current window, or null if the activity is not
474 * visual.
475 */
476 public Window getWindow() {
477 return mWindow;
478 }
479
480 /**
481 * Call {@link android.view.Window#getCurrentFocus} on the
482 * Window if this Activity to return the currently focused view.
483 *
484 * @return View The current View with focus or null.
485 *
486 * @see #getWindow
487 * @see android.view.Window#getCurrentFocus
488 */
489 public View getCurrentFocus() {
490 return mWindow != null ? mWindow.getCurrentFocus() : null;
491 }
492
493 /**
Alan Viverettef34ef742013-12-11 15:59:53 -0800494 * Finds a child view with the given identifier. Returns null if the
495 * specified child view does not exist or the dialog has not yet been fully
496 * created (for example, via {@link #show()} or {@link #create()}).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 *
498 * @param id the identifier of the view to find
Alan Viveretteec186702013-12-05 11:10:31 -0800499 * @return The view with the given id or null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 */
Scott Kennedyc0519552015-02-11 15:33:10 -0800501 @Nullable
Tor Norbye7b9c9122013-05-30 16:48:33 -0700502 public View findViewById(@IdRes int id) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 return mWindow.findViewById(id);
504 }
505
506 /**
507 * Set the screen content from a layout resource. The resource will be
508 * inflated, adding all top-level views to the screen.
509 *
510 * @param layoutResID Resource ID to be inflated.
511 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700512 public void setContentView(@LayoutRes int layoutResID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 mWindow.setContentView(layoutResID);
514 }
515
516 /**
517 * Set the screen content to an explicit view. This view is placed
518 * directly into the screen's view hierarchy. It can itself be a complex
Alan Viveretteec186702013-12-05 11:10:31 -0800519 * view hierarchy.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 *
521 * @param view The desired content to display.
522 */
523 public void setContentView(View view) {
524 mWindow.setContentView(view);
525 }
526
527 /**
528 * Set the screen content to an explicit view. This view is placed
529 * directly into the screen's view hierarchy. It can itself be a complex
530 * view hierarhcy.
531 *
532 * @param view The desired content to display.
533 * @param params Layout parameters for the view.
534 */
535 public void setContentView(View view, ViewGroup.LayoutParams params) {
536 mWindow.setContentView(view, params);
537 }
538
539 /**
540 * Add an additional content view to the screen. Added after any existing
541 * ones in the screen -- existing views are NOT removed.
542 *
543 * @param view The desired content to display.
544 * @param params Layout parameters for the view.
545 */
546 public void addContentView(View view, ViewGroup.LayoutParams params) {
547 mWindow.addContentView(view, params);
548 }
549
550 /**
551 * Set the title text for this dialog's window.
552 *
553 * @param title The new text to display in the title.
554 */
555 public void setTitle(CharSequence title) {
556 mWindow.setTitle(title);
557 mWindow.getAttributes().setTitle(title);
558 }
559
560 /**
561 * Set the title text for this dialog's window. The text is retrieved
562 * from the resources with the supplied identifier.
563 *
564 * @param titleId the title's text resource identifier
565 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700566 public void setTitle(@StringRes int titleId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 setTitle(mContext.getText(titleId));
568 }
569
570 /**
571 * A key was pressed down.
572 *
573 * <p>If the focused view didn't want this event, this method is called.
574 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700575 * <p>The default implementation consumed the KEYCODE_BACK to later
576 * handle it in {@link #onKeyUp}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 *
578 * @see #onKeyUp
579 * @see android.view.KeyEvent
580 */
581 public boolean onKeyDown(int keyCode, KeyEvent event) {
582 if (keyCode == KeyEvent.KEYCODE_BACK) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700583 event.startTracking();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 return true;
585 }
586
587 return false;
588 }
589
590 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700591 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
592 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
593 * the event).
594 */
595 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
596 return false;
597 }
598
599 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 * A key was released.
601 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700602 * <p>The default implementation handles KEYCODE_BACK to close the
603 * dialog.
604 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 * @see #onKeyDown
606 * @see KeyEvent
607 */
608 public boolean onKeyUp(int keyCode, KeyEvent event) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700609 if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
610 && !event.isCanceled()) {
611 onBackPressed();
612 return true;
613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 return false;
615 }
616
617 /**
618 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
619 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
620 * the event).
621 */
622 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
623 return false;
624 }
625
626 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700627 * Called when the dialog has detected the user's press of the back
628 * key. The default implementation simply cancels the dialog (only if
629 * it is cancelable), but you can override this to do whatever you want.
630 */
631 public void onBackPressed() {
632 if (mCancelable) {
633 cancel();
634 }
635 }
Jeff Brown64da12a2011-01-04 19:57:47 -0800636
637 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +0900638 * Called when a key shortcut event is not handled by any of the views in the Dialog.
Jeff Brown64da12a2011-01-04 19:57:47 -0800639 * Override this method to implement global key shortcuts for the Dialog.
640 * Key shortcuts can also be implemented by setting the
641 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
642 *
643 * @param keyCode The value in event.getKeyCode().
644 * @param event Description of the key event.
645 * @return True if the key shortcut was handled.
646 */
647 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
648 return false;
649 }
650
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700651 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 * Called when a touch screen event was not handled by any of the views
653 * under it. This is most useful to process touch events that happen outside
654 * of your window bounds, where there is no view to receive it.
655 *
656 * @param event The touch screen event being processed.
657 * @return Return true if you have consumed the event, false if you haven't.
658 * The default implementation will cancel the dialog when a touch
659 * happens outside of the window bounds.
660 */
661 public boolean onTouchEvent(MotionEvent event) {
Dianne Hackborncfaf8872011-01-18 13:57:54 -0800662 if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 cancel();
664 return true;
665 }
666
667 return false;
668 }
669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 /**
671 * Called when the trackball was moved and not handled by any of the
672 * views inside of the activity. So, for example, if the trackball moves
673 * while focus is on a button, you will receive a call here because
674 * buttons do not normally do anything with trackball events. The call
675 * here happens <em>before</em> trackball movements are converted to
676 * DPAD key events, which then get sent back to the view hierarchy, and
677 * will be processed at the point for things like focus navigation.
678 *
679 * @param event The trackball event being processed.
680 *
681 * @return Return true if you have consumed the event, false if you haven't.
682 * The default implementation always returns false.
683 */
684 public boolean onTrackballEvent(MotionEvent event) {
685 return false;
686 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800687
688 /**
689 * Called when a generic motion event was not handled by any of the
690 * views inside of the dialog.
691 * <p>
Jeff Brown33bbfd22011-02-24 20:55:35 -0800692 * Generic motion events describe joystick movements, mouse hovers, track pad
693 * touches, scroll wheel movements and other input events. The
Jeff Browncb1404e2011-01-15 18:14:15 -0800694 * {@link MotionEvent#getSource() source} of the motion event specifies
695 * the class of input that was received. Implementations of this method
696 * must examine the bits in the source before processing the event.
697 * The following code example shows how this is done.
Jeff Brown33bbfd22011-02-24 20:55:35 -0800698 * </p><p>
699 * Generic motion events with source class
700 * {@link android.view.InputDevice#SOURCE_CLASS_POINTER}
701 * are delivered to the view under the pointer. All other generic motion events are
702 * delivered to the focused view.
703 * </p><p>
704 * See {@link View#onGenericMotionEvent(MotionEvent)} for an example of how to
705 * handle this event.
Jeff Browncb1404e2011-01-15 18:14:15 -0800706 * </p>
Jeff Browncb1404e2011-01-15 18:14:15 -0800707 *
708 * @param event The generic motion event being processed.
709 *
710 * @return Return true if you have consumed the event, false if you haven't.
711 * The default implementation always returns false.
712 */
713 public boolean onGenericMotionEvent(MotionEvent event) {
714 return false;
715 }
716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
718 if (mDecor != null) {
719 mWindowManager.updateViewLayout(mDecor, params);
720 }
721 }
722
723 public void onContentChanged() {
724 }
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 public void onWindowFocusChanged(boolean hasFocus) {
727 }
728
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700729 public void onAttachedToWindow() {
730 }
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700731
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700732 public void onDetachedFromWindow() {
733 }
Will Haldean Brownca6234e2014-02-12 10:23:41 -0800734
Adam Powell117b6952014-05-05 18:14:56 -0700735 /** @hide */
736 @Override
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700737 public void onWindowDismissed(boolean finishTask) {
Will Haldean Brownca6234e2014-02-12 10:23:41 -0800738 dismiss();
739 }
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 /**
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700742 * Called to process key events. You can override this to intercept all
743 * key events before they are dispatched to the window. Be sure to call
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 * this implementation for key events that should be handled normally.
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700745 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 * @param event The key event.
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700747 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 * @return boolean Return true if this event was consumed.
749 */
750 public boolean dispatchKeyEvent(KeyEvent event) {
751 if ((mOnKeyListener != null) && (mOnKeyListener.onKey(this, event.getKeyCode(), event))) {
752 return true;
753 }
754 if (mWindow.superDispatchKeyEvent(event)) {
755 return true;
756 }
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700757 return event.dispatch(this, mDecor != null
758 ? mDecor.getKeyDispatcherState() : null, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 }
760
761 /**
Jeff Brown64da12a2011-01-04 19:57:47 -0800762 * Called to process a key shortcut event.
763 * You can override this to intercept all key shortcut events before they are
764 * dispatched to the window. Be sure to call this implementation for key shortcut
765 * events that should be handled normally.
766 *
767 * @param event The key shortcut event.
768 * @return True if this event was consumed.
769 */
770 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
771 if (mWindow.superDispatchKeyShortcutEvent(event)) {
772 return true;
773 }
774 return onKeyShortcut(event.getKeyCode(), event);
775 }
776
777 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 * Called to process touch screen events. You can override this to
779 * intercept all touch screen events before they are dispatched to the
780 * window. Be sure to call this implementation for touch screen events
781 * that should be handled normally.
782 *
783 * @param ev The touch screen event.
784 *
785 * @return boolean Return true if this event was consumed.
786 */
787 public boolean dispatchTouchEvent(MotionEvent ev) {
788 if (mWindow.superDispatchTouchEvent(ev)) {
789 return true;
790 }
791 return onTouchEvent(ev);
792 }
793
794 /**
795 * Called to process trackball events. You can override this to
796 * intercept all trackball events before they are dispatched to the
797 * window. Be sure to call this implementation for trackball events
798 * that should be handled normally.
799 *
800 * @param ev The trackball event.
801 *
802 * @return boolean Return true if this event was consumed.
803 */
804 public boolean dispatchTrackballEvent(MotionEvent ev) {
805 if (mWindow.superDispatchTrackballEvent(ev)) {
806 return true;
807 }
808 return onTrackballEvent(ev);
809 }
810
Jeff Browncb1404e2011-01-15 18:14:15 -0800811 /**
812 * Called to process generic motion events. You can override this to
813 * intercept all generic motion events before they are dispatched to the
814 * window. Be sure to call this implementation for generic motion events
815 * that should be handled normally.
816 *
817 * @param ev The generic motion event.
818 *
819 * @return boolean Return true if this event was consumed.
820 */
821 public boolean dispatchGenericMotionEvent(MotionEvent ev) {
822 if (mWindow.superDispatchGenericMotionEvent(ev)) {
823 return true;
824 }
825 return onGenericMotionEvent(ev);
826 }
827
svetoslavganov75986cf2009-05-14 22:28:01 -0700828 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
829 event.setClassName(getClass().getName());
830 event.setPackageName(mContext.getPackageName());
831
832 LayoutParams params = getWindow().getAttributes();
Romain Guy980a9382010-01-08 15:06:28 -0800833 boolean isFullScreen = (params.width == LayoutParams.MATCH_PARENT) &&
834 (params.height == LayoutParams.MATCH_PARENT);
svetoslavganov75986cf2009-05-14 22:28:01 -0700835 event.setFullScreen(isFullScreen);
836
837 return false;
838 }
839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 /**
841 * @see Activity#onCreatePanelView(int)
842 */
843 public View onCreatePanelView(int featureId) {
844 return null;
845 }
846
847 /**
848 * @see Activity#onCreatePanelMenu(int, Menu)
849 */
850 public boolean onCreatePanelMenu(int featureId, Menu menu) {
851 if (featureId == Window.FEATURE_OPTIONS_PANEL) {
852 return onCreateOptionsMenu(menu);
853 }
854
855 return false;
856 }
857
858 /**
859 * @see Activity#onPreparePanel(int, View, Menu)
860 */
861 public boolean onPreparePanel(int featureId, View view, Menu menu) {
862 if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
863 boolean goforit = onPrepareOptionsMenu(menu);
864 return goforit && menu.hasVisibleItems();
865 }
866 return true;
867 }
868
869 /**
870 * @see Activity#onMenuOpened(int, Menu)
871 */
872 public boolean onMenuOpened(int featureId, Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800873 if (featureId == Window.FEATURE_ACTION_BAR) {
874 mActionBar.dispatchMenuVisibilityChanged(true);
875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 return true;
877 }
878
879 /**
880 * @see Activity#onMenuItemSelected(int, MenuItem)
881 */
882 public boolean onMenuItemSelected(int featureId, MenuItem item) {
883 return false;
884 }
885
886 /**
887 * @see Activity#onPanelClosed(int, Menu)
888 */
889 public void onPanelClosed(int featureId, Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800890 if (featureId == Window.FEATURE_ACTION_BAR) {
891 mActionBar.dispatchMenuVisibilityChanged(false);
892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 }
894
895 /**
896 * It is usually safe to proxy this call to the owner activity's
897 * {@link Activity#onCreateOptionsMenu(Menu)} if the client desires the same
898 * menu for this Dialog.
899 *
900 * @see Activity#onCreateOptionsMenu(Menu)
901 * @see #getOwnerActivity()
902 */
903 public boolean onCreateOptionsMenu(Menu menu) {
904 return true;
905 }
906
907 /**
908 * It is usually safe to proxy this call to the owner activity's
909 * {@link Activity#onPrepareOptionsMenu(Menu)} if the client desires the
910 * same menu for this Dialog.
911 *
912 * @see Activity#onPrepareOptionsMenu(Menu)
913 * @see #getOwnerActivity()
914 */
915 public boolean onPrepareOptionsMenu(Menu menu) {
916 return true;
917 }
918
919 /**
920 * @see Activity#onOptionsItemSelected(MenuItem)
921 */
922 public boolean onOptionsItemSelected(MenuItem item) {
923 return false;
924 }
925
926 /**
927 * @see Activity#onOptionsMenuClosed(Menu)
928 */
929 public void onOptionsMenuClosed(Menu menu) {
930 }
931
932 /**
933 * @see Activity#openOptionsMenu()
934 */
935 public void openOptionsMenu() {
Jose Lima7a22fc62015-01-23 17:24:22 -0800936 if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
937 mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 }
Jose Lima7a22fc62015-01-23 17:24:22 -0800940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 /**
942 * @see Activity#closeOptionsMenu()
943 */
944 public void closeOptionsMenu() {
Jose Lima7a22fc62015-01-23 17:24:22 -0800945 if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
946 mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 }
949
950 /**
Adam Powelle67a9dc2010-08-17 17:28:56 -0700951 * @see Activity#invalidateOptionsMenu()
952 */
953 public void invalidateOptionsMenu() {
Jose Lima7a22fc62015-01-23 17:24:22 -0800954 if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
955 mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
956 }
Adam Powelle67a9dc2010-08-17 17:28:56 -0700957 }
958
959 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 * @see Activity#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)
961 */
962 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
963 }
964
965 /**
966 * @see Activity#registerForContextMenu(View)
967 */
968 public void registerForContextMenu(View view) {
969 view.setOnCreateContextMenuListener(this);
970 }
971
972 /**
973 * @see Activity#unregisterForContextMenu(View)
974 */
975 public void unregisterForContextMenu(View view) {
976 view.setOnCreateContextMenuListener(null);
977 }
978
979 /**
980 * @see Activity#openContextMenu(View)
981 */
982 public void openContextMenu(View view) {
983 view.showContextMenu();
984 }
985
986 /**
987 * @see Activity#onContextItemSelected(MenuItem)
988 */
989 public boolean onContextItemSelected(MenuItem item) {
990 return false;
991 }
Clara Bayarri4423d912015-03-02 19:42:48 +0000992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 /**
994 * @see Activity#onContextMenuClosed(Menu)
995 */
996 public void onContextMenuClosed(Menu menu) {
997 }
Clara Bayarri4423d912015-03-02 19:42:48 +0000998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 /**
1000 * This hook is called when the user signals the desire to start a search.
1001 */
Tim Kilbourn6a975b32015-04-09 17:14:34 -07001002 public boolean onSearchRequested(SearchEvent searchEvent) {
1003 mSearchEvent = searchEvent;
1004 return onSearchRequested();
1005 }
1006
1007 /**
1008 * This hook is called when the user signals the desire to start a search.
1009 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 public boolean onSearchRequested() {
Karl Rosaen53d24af2009-07-14 14:58:10 -07001011 final SearchManager searchManager = (SearchManager) mContext
1012 .getSystemService(Context.SEARCH_SERVICE);
1013
Bjorn Bringertb8144a92010-02-22 20:48:57 +00001014 // associate search with owner activity
Karl Rosaen7bafed82009-09-04 11:15:21 -07001015 final ComponentName appName = getAssociatedActivity();
lge-aosp06ca9972011-03-15 10:25:57 +09001016 if (appName != null && searchManager.getSearchableInfo(appName) != null) {
Bjorn Bringertb8144a92010-02-22 20:48:57 +00001017 searchManager.startSearch(null, false, appName, null, false);
1018 dismiss();
1019 return true;
1020 } else {
1021 return false;
1022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 }
1024
Clara Bayarri4423d912015-03-02 19:42:48 +00001025 /**
Tim Kilbourn6a975b32015-04-09 17:14:34 -07001026 * During the onSearchRequested() callbacks, this function will return the
1027 * {@link SearchEvent} that triggered the callback, if it exists.
1028 *
1029 * @return SearchEvent The SearchEvent that triggered the {@link
1030 * #onSearchRequested} callback.
1031 */
1032 public final SearchEvent getSearchEvent() {
1033 return mSearchEvent;
1034 }
1035
1036 /**
Clara Bayarri4423d912015-03-02 19:42:48 +00001037 * {@inheritDoc}
1038 */
1039 @Override
Adam Powelldebf3be2010-11-15 18:58:48 -08001040 public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
Clara Bayarri4423d912015-03-02 19:42:48 +00001041 if (mActionBar != null && mActionModeTypeStarting == ActionMode.TYPE_PRIMARY) {
Adam Powelldec9dfd2010-08-09 15:27:54 -07001042 return mActionBar.startActionMode(callback);
1043 }
Adam Powell6e346362010-07-23 10:18:23 -07001044 return null;
1045 }
1046
Adam Powellcfe9aee2011-11-01 14:56:27 -07001047 /**
1048 * {@inheritDoc}
Clara Bayarri4423d912015-03-02 19:42:48 +00001049 */
1050 @Override
1051 public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
1052 try {
1053 mActionModeTypeStarting = type;
1054 return onWindowStartingActionMode(callback);
1055 } finally {
1056 mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
1057 }
1058 }
1059
1060 /**
1061 * {@inheritDoc}
Adam Powellcfe9aee2011-11-01 14:56:27 -07001062 *
1063 * Note that if you override this method you should always call through
1064 * to the superclass implementation by calling super.onActionModeStarted(mode).
1065 */
Tor Norbyec615c6f2015-03-02 10:11:44 -08001066 @CallSuper
Adam Powelldebf3be2010-11-15 18:58:48 -08001067 public void onActionModeStarted(ActionMode mode) {
Adam Powellcfe9aee2011-11-01 14:56:27 -07001068 mActionMode = mode;
Adam Powelldebf3be2010-11-15 18:58:48 -08001069 }
1070
Adam Powellcfe9aee2011-11-01 14:56:27 -07001071 /**
1072 * {@inheritDoc}
1073 *
1074 * Note that if you override this method you should always call through
1075 * to the superclass implementation by calling super.onActionModeFinished(mode).
1076 */
Tor Norbyec615c6f2015-03-02 10:11:44 -08001077 @CallSuper
Adam Powelldebf3be2010-11-15 18:58:48 -08001078 public void onActionModeFinished(ActionMode mode) {
Adam Powellcfe9aee2011-11-01 14:56:27 -07001079 if (mode == mActionMode) {
1080 mActionMode = null;
1081 }
Adam Powelldebf3be2010-11-15 18:58:48 -08001082 }
1083
Karl Rosaen7bafed82009-09-04 11:15:21 -07001084 /**
Clara Bayarri75e09792015-07-29 16:20:40 +01001085 * {@inheritDoc}
1086 */
1087 @Override
1088 public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
1089 }
1090
1091 /**
Adam Powelldec9dfd2010-08-09 15:27:54 -07001092 * @return The activity associated with this dialog, or null if there is no associated activity.
Karl Rosaen7bafed82009-09-04 11:15:21 -07001093 */
1094 private ComponentName getAssociatedActivity() {
1095 Activity activity = mOwnerActivity;
1096 Context context = getContext();
1097 while (activity == null && context != null) {
1098 if (context instanceof Activity) {
1099 activity = (Activity) context; // found it!
1100 } else {
1101 context = (context instanceof ContextWrapper) ?
1102 ((ContextWrapper) context).getBaseContext() : // unwrap one level
1103 null; // done
1104 }
1105 }
1106 return activity == null ? null : activity.getComponentName();
1107 }
1108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109
1110 /**
1111 * Request that key events come to this dialog. Use this if your
1112 * dialog has no views with focus, but the dialog still wants
1113 * a chance to process key events.
1114 *
1115 * @param get true if the dialog should receive key events, false otherwise
1116 * @see android.view.Window#takeKeyEvents
1117 */
1118 public void takeKeyEvents(boolean get) {
1119 mWindow.takeKeyEvents(get);
1120 }
1121
1122 /**
1123 * Enable extended window features. This is a convenience for calling
1124 * {@link android.view.Window#requestFeature getWindow().requestFeature()}.
1125 *
1126 * @param featureId The desired feature as defined in
1127 * {@link android.view.Window}.
1128 * @return Returns true if the requested feature is supported and now
1129 * enabled.
1130 *
1131 * @see android.view.Window#requestFeature
1132 */
1133 public final boolean requestWindowFeature(int featureId) {
1134 return getWindow().requestFeature(featureId);
1135 }
1136
1137 /**
1138 * Convenience for calling
1139 * {@link android.view.Window#setFeatureDrawableResource}.
1140 */
Tor Norbye7b9c9122013-05-30 16:48:33 -07001141 public final void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 getWindow().setFeatureDrawableResource(featureId, resId);
1143 }
1144
1145 /**
1146 * Convenience for calling
1147 * {@link android.view.Window#setFeatureDrawableUri}.
1148 */
1149 public final void setFeatureDrawableUri(int featureId, Uri uri) {
1150 getWindow().setFeatureDrawableUri(featureId, uri);
1151 }
1152
1153 /**
1154 * Convenience for calling
1155 * {@link android.view.Window#setFeatureDrawable(int, Drawable)}.
1156 */
1157 public final void setFeatureDrawable(int featureId, Drawable drawable) {
1158 getWindow().setFeatureDrawable(featureId, drawable);
1159 }
1160
1161 /**
1162 * Convenience for calling
1163 * {@link android.view.Window#setFeatureDrawableAlpha}.
1164 */
1165 public final void setFeatureDrawableAlpha(int featureId, int alpha) {
1166 getWindow().setFeatureDrawableAlpha(featureId, alpha);
1167 }
1168
1169 public LayoutInflater getLayoutInflater() {
1170 return getWindow().getLayoutInflater();
1171 }
1172
1173 /**
1174 * Sets whether this dialog is cancelable with the
1175 * {@link KeyEvent#KEYCODE_BACK BACK} key.
1176 */
1177 public void setCancelable(boolean flag) {
1178 mCancelable = flag;
1179 }
1180
1181 /**
1182 * Sets whether this dialog is canceled when touched outside the window's
1183 * bounds. If setting to true, the dialog is set to be cancelable if not
1184 * already set.
1185 *
1186 * @param cancel Whether the dialog should be canceled when touched outside
1187 * the window.
1188 */
1189 public void setCanceledOnTouchOutside(boolean cancel) {
1190 if (cancel && !mCancelable) {
1191 mCancelable = true;
1192 }
1193
Dianne Hackborncfaf8872011-01-18 13:57:54 -08001194 mWindow.setCloseOnTouchOutside(cancel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 }
1196
1197 /**
1198 * Cancel the dialog. This is essentially the same as calling {@link #dismiss()}, but it will
1199 * also call your {@link DialogInterface.OnCancelListener} (if registered).
1200 */
1201 public void cancel() {
Dianne Hackborn8b4cac12011-01-03 13:58:14 -08001202 if (!mCanceled && mCancelMessage != null) {
1203 mCanceled = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 // Obtain a new message so this dialog can be re-used
1205 Message.obtain(mCancelMessage).sendToTarget();
1206 }
1207 dismiss();
1208 }
1209
1210 /**
1211 * Set a listener to be invoked when the dialog is canceled.
Adam Powell7f02dc52012-08-27 13:35:16 -07001212 *
1213 * <p>This will only be invoked when the dialog is canceled.
1214 * Cancel events alone will not capture all ways that
1215 * the dialog might be dismissed. If the creator needs
1216 * to know when a dialog is dismissed in general, use
1217 * {@link #setOnDismissListener}.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 *
1219 * @param listener The {@link DialogInterface.OnCancelListener} to use.
1220 */
1221 public void setOnCancelListener(final OnCancelListener listener) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001222 if (mCancelAndDismissTaken != null) {
1223 throw new IllegalStateException(
1224 "OnCancelListener is already taken by "
1225 + mCancelAndDismissTaken + " and can not be replaced.");
1226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 if (listener != null) {
Romain Guy045163a2009-07-14 13:59:33 -07001228 mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 } else {
1230 mCancelMessage = null;
1231 }
1232 }
1233
1234 /**
1235 * Set a message to be sent when the dialog is canceled.
1236 * @param msg The msg to send when the dialog is canceled.
1237 * @see #setOnCancelListener(android.content.DialogInterface.OnCancelListener)
1238 */
1239 public void setCancelMessage(final Message msg) {
1240 mCancelMessage = msg;
1241 }
1242
1243 /**
1244 * Set a listener to be invoked when the dialog is dismissed.
1245 * @param listener The {@link DialogInterface.OnDismissListener} to use.
1246 */
1247 public void setOnDismissListener(final OnDismissListener listener) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001248 if (mCancelAndDismissTaken != null) {
1249 throw new IllegalStateException(
1250 "OnDismissListener is already taken by "
1251 + mCancelAndDismissTaken + " and can not be replaced.");
1252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 if (listener != null) {
Romain Guy045163a2009-07-14 13:59:33 -07001254 mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 } else {
1256 mDismissMessage = null;
1257 }
1258 }
1259
1260 /**
Romain Guy045163a2009-07-14 13:59:33 -07001261 * Sets a listener to be invoked when the dialog is shown.
Ficus Kirkpatrick130a8b72010-01-14 15:39:43 -08001262 * @param listener The {@link DialogInterface.OnShowListener} to use.
Romain Guy045163a2009-07-14 13:59:33 -07001263 */
1264 public void setOnShowListener(OnShowListener listener) {
1265 if (listener != null) {
1266 mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
1267 } else {
1268 mShowMessage = null;
1269 }
1270 }
1271
1272 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 * Set a message to be sent when the dialog is dismissed.
1274 * @param msg The msg to send when the dialog is dismissed.
1275 */
1276 public void setDismissMessage(final Message msg) {
1277 mDismissMessage = msg;
1278 }
1279
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001280 /** @hide */
1281 public boolean takeCancelAndDismissListeners(String msg, final OnCancelListener cancel,
1282 final OnDismissListener dismiss) {
1283 if (mCancelAndDismissTaken != null) {
1284 mCancelAndDismissTaken = null;
1285 } else if (mCancelMessage != null || mDismissMessage != null) {
1286 return false;
1287 }
1288
1289 setOnCancelListener(cancel);
1290 setOnDismissListener(dismiss);
1291 mCancelAndDismissTaken = msg;
1292
1293 return true;
1294 }
1295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 /**
1297 * By default, this will use the owner Activity's suggested stream type.
1298 *
1299 * @see Activity#setVolumeControlStream(int)
1300 * @see #setOwnerActivity(Activity)
1301 */
1302 public final void setVolumeControlStream(int streamType) {
1303 getWindow().setVolumeControlStream(streamType);
1304 }
1305
1306 /**
1307 * @see Activity#getVolumeControlStream()
1308 */
1309 public final int getVolumeControlStream() {
1310 return getWindow().getVolumeControlStream();
1311 }
1312
1313 /**
1314 * Sets the callback that will be called if a key is dispatched to the dialog.
1315 */
1316 public void setOnKeyListener(final OnKeyListener onKeyListener) {
1317 mOnKeyListener = onKeyListener;
1318 }
1319
Romain Guy045163a2009-07-14 13:59:33 -07001320 private static final class ListenersHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 private WeakReference<DialogInterface> mDialog;
1322
Romain Guy045163a2009-07-14 13:59:33 -07001323 public ListenersHandler(Dialog dialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 mDialog = new WeakReference<DialogInterface>(dialog);
1325 }
1326
1327 @Override
1328 public void handleMessage(Message msg) {
1329 switch (msg.what) {
1330 case DISMISS:
1331 ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
1332 break;
1333 case CANCEL:
1334 ((OnCancelListener) msg.obj).onCancel(mDialog.get());
1335 break;
Romain Guy045163a2009-07-14 13:59:33 -07001336 case SHOW:
1337 ((OnShowListener) msg.obj).onShow(mDialog.get());
1338 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 }
1340 }
1341 }
1342}