blob: 6e2c464e9a371bfc50eb6e85d5c0b9380ab43bb9 [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
Alan Viverette48728c22016-04-01 15:00:10 -040019import com.android.internal.R;
20import com.android.internal.app.WindowDecorActionBar;
21import com.android.internal.policy.PhoneWindow;
22
Tor Norbyec615c6f2015-03-02 10:11:44 -080023import android.annotation.CallSuper;
Tor Norbye7b9c9122013-05-30 16:48:33 -070024import android.annotation.DrawableRes;
25import android.annotation.IdRes;
26import android.annotation.LayoutRes;
Alan Viverette682a4332015-04-10 11:05:50 -070027import android.annotation.NonNull;
Scott Kennedyc0519552015-02-11 15:33:10 -080028import android.annotation.Nullable;
Clara Bayarri75e09792015-07-29 16:20:40 +010029import android.annotation.StringRes;
Alan Viverette682a4332015-04-10 11:05:50 -070030import android.annotation.StyleRes;
Karl Rosaen53d24af2009-07-14 14:58:10 -070031import android.content.ComponentName;
Adam Powell6e346362010-07-23 10:18:23 -070032import android.content.Context;
Karl Rosaen7bafed82009-09-04 11:15:21 -070033import android.content.ContextWrapper;
Adam Powell6e346362010-07-23 10:18:23 -070034import android.content.DialogInterface;
Robert Carrd7dbec72016-10-05 13:13:21 -070035import android.content.res.Configuration;
Jorim Jaggib10e33f2015-02-04 21:57:40 +010036import android.content.pm.ApplicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.graphics.drawable.Drawable;
38import android.net.Uri;
svetoslavganov75986cf2009-05-14 22:28:01 -070039import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.Handler;
Svetoslav Ganov44bfdd82012-01-26 10:00:18 -080041import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.Message;
Adam Powell89fc3ac2011-11-01 18:00:44 -070043import android.util.Log;
Adam Powell2fbf4de62010-09-30 15:46:46 -070044import android.util.TypedValue;
Adam Powelldec9dfd2010-08-09 15:27:54 -070045import android.view.ActionMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.view.ContextMenu;
Adam Powell6e346362010-07-23 10:18:23 -070047import android.view.ContextMenu.ContextMenuInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.view.ContextThemeWrapper;
49import android.view.Gravity;
50import android.view.KeyEvent;
svetoslavganov75986cf2009-05-14 22:28:01 -070051import android.view.LayoutInflater;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.view.Menu;
53import android.view.MenuItem;
54import android.view.MotionEvent;
Tim Kilbourn6a975b32015-04-09 17:14:34 -070055import android.view.SearchEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.view.View;
Adam Powell6e346362010-07-23 10:18:23 -070057import android.view.View.OnCreateContextMenuListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.view.ViewGroup;
Adam Powell6e346362010-07-23 10:18:23 -070059import android.view.ViewGroup.LayoutParams;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.view.Window;
61import android.view.WindowManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070062import android.view.accessibility.AccessibilityEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063
64import java.lang.ref.WeakReference;
65
66/**
67 * Base class for Dialogs.
68 *
69 * <p>Note: Activities provide a facility to manage the creation, saving and
70 * restoring of dialogs. See {@link Activity#onCreateDialog(int)},
71 * {@link Activity#onPrepareDialog(int, Dialog)},
72 * {@link Activity#showDialog(int)}, and {@link Activity#dismissDialog(int)}. If
73 * these methods are used, {@link #getOwnerActivity()} will return the Activity
74 * that managed this dialog.
75 *
76 * <p>Often you will want to have a Dialog display on top of the current
77 * input method, because there is no reason for it to accept text. You can
78 * do this by setting the {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
79 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} window flag (assuming
80 * your Dialog takes input focus, as it the default) with the following code:
81 *
82 * <pre>
Joe Fernandez558459f2011-10-13 16:47:36 -070083 * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
84 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);</pre>
85 *
86 * <div class="special reference">
87 * <h3>Developer Guides</h3>
88 * <p>For more information about creating dialogs, read the
89 * <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a> developer guide.</p>
90 * </div>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 */
92public class Dialog implements DialogInterface, Window.Callback,
Adam Powell117b6952014-05-05 18:14:56 -070093 KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {
Adam Powell89fc3ac2011-11-01 18:00:44 -070094 private static final String TAG = "Dialog";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 private Activity mOwnerActivity;
Alan Viverette48728c22016-04-01 15:00:10 -040096
97 private final WindowManager mWindowManager;
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 final Context mContext;
Alan Viverette48728c22016-04-01 15:00:10 -0400100 final Window mWindow;
101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 View mDecor;
Alan Viverette48728c22016-04-01 15:00:10 -0400103
Adam Powelle43340c2014-03-17 19:10:43 -0700104 private ActionBar mActionBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 /**
106 * This field should be made private, so it is hidden from the SDK.
107 * {@hide}
108 */
109 protected boolean mCancelable = true;
svetoslavganov75986cf2009-05-14 22:28:01 -0700110
Dianne Hackbornf812fee2011-01-25 14:54:29 -0800111 private String mCancelAndDismissTaken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 private Message mCancelMessage;
113 private Message mDismissMessage;
Romain Guy045163a2009-07-14 13:59:33 -0700114 private Message mShowMessage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 private OnKeyListener mOnKeyListener;
117
118 private boolean mCreated = false;
119 private boolean mShowing = false;
Dianne Hackborn8b4cac12011-01-03 13:58:14 -0800120 private boolean mCanceled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 private final Handler mHandler = new Handler();
123
Romain Guy7883c972010-03-01 16:39:17 -0800124 private static final int DISMISS = 0x43;
125 private static final int CANCEL = 0x44;
126 private static final int SHOW = 0x45;
127
Alan Viverette48728c22016-04-01 15:00:10 -0400128 private final Handler mListenersHandler;
Romain Guy7883c972010-03-01 16:39:17 -0800129
Tim Kilbourn6a975b32015-04-09 17:14:34 -0700130 private SearchEvent mSearchEvent;
131
Adam Powellcfe9aee2011-11-01 14:56:27 -0700132 private ActionMode mActionMode;
133
Clara Bayarri4423d912015-03-02 19:42:48 +0000134 private int mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
135
Alan Viverette48728c22016-04-01 15:00:10 -0400136 private final Runnable mDismissAction = this::dismissDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137
138 /**
Alan Viverette5696f042015-04-08 11:03:32 -0700139 * Creates a dialog window that uses the default dialog theme.
140 * <p>
141 * The supplied {@code context} is used to obtain the window manager and
142 * base theme used to present the dialog.
143 *
144 * @param context the context in which the dialog should run
145 * @see android.R.styleable#Theme_dialogTheme
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 */
Alan Viverette682a4332015-04-10 11:05:50 -0700147 public Dialog(@NonNull Context context) {
Dianne Hackborne79b5542011-01-27 15:18:46 -0800148 this(context, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 }
150
151 /**
Alan Viverette5696f042015-04-08 11:03:32 -0700152 * Creates a dialog window that uses a custom dialog style.
153 * <p>
154 * The supplied {@code context} is used to obtain the window manager and
155 * base theme used to present the dialog.
156 * <p>
157 * The supplied {@code theme} is applied on top of the context's theme. See
158 * <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">
159 * Style and Theme Resources</a> for more information about defining and
160 * using styles.
Jorim Jaggib10e33f2015-02-04 21:57:40 +0100161 *
Alan Viverette5696f042015-04-08 11:03:32 -0700162 * @param context the context in which the dialog should run
Alan Viverette682a4332015-04-10 11:05:50 -0700163 * @param themeResId a style resource describing the theme to use for the
Alan Viverette5696f042015-04-08 11:03:32 -0700164 * window, or {@code 0} to use the default dialog theme
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 */
Alan Viverette682a4332015-04-10 11:05:50 -0700166 public Dialog(@NonNull Context context, @StyleRes int themeResId) {
167 this(context, themeResId, true);
Dianne Hackborne79b5542011-01-27 15:18:46 -0800168 }
169
Alan Viverette682a4332015-04-10 11:05:50 -0700170 Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
Jeff Browna492c3a2012-08-23 19:48:44 -0700171 if (createContextThemeWrapper) {
Alan Viverette682a4332015-04-10 11:05:50 -0700172 if (themeResId == 0) {
Alan Viverette5696f042015-04-08 11:03:32 -0700173 final TypedValue outValue = new TypedValue();
174 context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
Alan Viverette682a4332015-04-10 11:05:50 -0700175 themeResId = outValue.resourceId;
Jeff Browna492c3a2012-08-23 19:48:44 -0700176 }
Alan Viverette682a4332015-04-10 11:05:50 -0700177 mContext = new ContextThemeWrapper(context, themeResId);
Jeff Browna492c3a2012-08-23 19:48:44 -0700178 } else {
179 mContext = context;
Adam Powell2fbf4de62010-09-30 15:46:46 -0700180 }
181
Alan Viverette682a4332015-04-10 11:05:50 -0700182 mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Alan Viverette5696f042015-04-08 11:03:32 -0700183
184 final Window w = new PhoneWindow(mContext);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 mWindow = w;
186 w.setCallback(this);
Adam Powell117b6952014-05-05 18:14:56 -0700187 w.setOnWindowDismissedCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 w.setWindowManager(mWindowManager, null, null);
189 w.setGravity(Gravity.CENTER);
Alan Viverette5696f042015-04-08 11:03:32 -0700190
Romain Guy045163a2009-07-14 13:59:33 -0700191 mListenersHandler = new ListenersHandler(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 }
Jeff Browna492c3a2012-08-23 19:48:44 -0700193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 /**
195 * @deprecated
196 * @hide
197 */
198 @Deprecated
Alan Viverette48728c22016-04-01 15:00:10 -0400199 protected Dialog(@NonNull Context context, boolean cancelable,
200 @Nullable Message cancelCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 this(context);
202 mCancelable = cancelable;
203 mCancelMessage = cancelCallback;
204 }
205
Alan Viverette682a4332015-04-10 11:05:50 -0700206 protected Dialog(@NonNull Context context, boolean cancelable,
Alan Viverette48728c22016-04-01 15:00:10 -0400207 @Nullable OnCancelListener cancelListener) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 this(context);
209 mCancelable = cancelable;
210 setOnCancelListener(cancelListener);
211 }
212
213 /**
214 * Retrieve the Context this Dialog is running in.
215 *
Adam Powellc49c1732010-09-28 16:03:15 -0700216 * @return Context The Context used by the Dialog.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 */
Alan Viverette48728c22016-04-01 15:00:10 -0400218 public final @NonNull Context getContext() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 return mContext;
220 }
221
222 /**
Adam Powelldec9dfd2010-08-09 15:27:54 -0700223 * Retrieve the {@link ActionBar} attached to this dialog, if present.
224 *
225 * @return The ActionBar attached to the dialog or null if no ActionBar is present.
226 */
Alan Viverette48728c22016-04-01 15:00:10 -0400227 public @Nullable ActionBar getActionBar() {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700228 return mActionBar;
229 }
230
231 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 * Sets the Activity that owns this dialog. An example use: This Dialog will
233 * use the suggested volume control stream of the Activity.
234 *
235 * @param activity The Activity that owns this dialog.
236 */
Alan Viverette48728c22016-04-01 15:00:10 -0400237 public final void setOwnerActivity(@NonNull Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 mOwnerActivity = activity;
239
240 getWindow().setVolumeControlStream(mOwnerActivity.getVolumeControlStream());
241 }
242
243 /**
244 * Returns the Activity that owns this Dialog. For example, if
245 * {@link Activity#showDialog(int)} is used to show this Dialog, that
246 * Activity will be the owner (by default). Depending on how this dialog was
247 * created, this may return null.
248 *
249 * @return The Activity that owns this Dialog.
250 */
Alan Viverette48728c22016-04-01 15:00:10 -0400251 public final @Nullable Activity getOwnerActivity() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 return mOwnerActivity;
253 }
254
255 /**
256 * @return Whether the dialog is currently showing.
257 */
258 public boolean isShowing() {
259 return mShowing;
260 }
261
262 /**
Alan Viverettef34ef742013-12-11 15:59:53 -0800263 * Forces immediate creation of the dialog.
264 * <p>
265 * Note that you should not override this method to perform dialog creation.
266 * Rather, override {@link #onCreate(Bundle)}.
267 */
268 public void create() {
269 if (!mCreated) {
270 dispatchOnCreate(null);
271 }
272 }
273
274 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 * Start the dialog and display it on screen. The window is placed in the
276 * application layer and opaque. Note that you should not override this
277 * method to do initialization when the dialog is shown, instead implement
278 * that in {@link #onStart}.
279 */
280 public void show() {
281 if (mShowing) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700282 if (mDecor != null) {
Adam Powelle67a9dc2010-08-17 17:28:56 -0700283 if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
284 mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
285 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700286 mDecor.setVisibility(View.VISIBLE);
287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 return;
289 }
290
Dianne Hackborn8b4cac12011-01-03 13:58:14 -0800291 mCanceled = false;
Robert Carrd7dbec72016-10-05 13:13:21 -0700292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 if (!mCreated) {
294 dispatchOnCreate(null);
Robert Carrd7dbec72016-10-05 13:13:21 -0700295 } else {
296 // Fill the DecorView in on any configuration changes that
297 // may have occured while it was removed from the WindowManager.
298 final Configuration config = mContext.getResources().getConfiguration();
299 mWindow.getDecorView().dispatchConfigurationChanged(config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 }
301
302 onStart();
303 mDecor = mWindow.getDecorView();
Adam Powelldec9dfd2010-08-09 15:27:54 -0700304
305 if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
Adam Powell04fe6eb2013-05-31 14:39:48 -0700306 final ApplicationInfo info = mContext.getApplicationInfo();
307 mWindow.setDefaultIcon(info.icon);
308 mWindow.setDefaultLogo(info.logo);
Adam Powelle43340c2014-03-17 19:10:43 -0700309 mActionBar = new WindowDecorActionBar(this);
Adam Powelldec9dfd2010-08-09 15:27:54 -0700310 }
311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 WindowManager.LayoutParams l = mWindow.getAttributes();
313 if ((l.softInputMode
314 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
315 WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
316 nl.copyFrom(l);
317 nl.softInputMode |=
318 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
319 l = nl;
320 }
Romain Guy045163a2009-07-14 13:59:33 -0700321
Alan Viverette48728c22016-04-01 15:00:10 -0400322 mWindowManager.addView(mDecor, l);
323 mShowing = true;
324
325 sendShowMessage();
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
Alan Viverette48728c22016-04-01 15:00:10 -0400391 // internal method to make sure mCreated is set properly without requiring
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 // 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}.
Alan Viverette48728c22016-04-01 15:00:10 -0400403 * @param savedInstanceState If this dialog is being reinitialized after a
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 * 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 */
Alan Viverette48728c22016-04-01 15:00:10 -0400436 public @NonNull Bundle onSaveInstanceState() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 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 */
Alan Viverette48728c22016-04-01 15:00:10 -0400455 public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 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 */
Alan Viverette48728c22016-04-01 15:00:10 -0400476 public @Nullable Window getWindow() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 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 */
Alan Viverette48728c22016-04-01 15:00:10 -0400489 public @Nullable View getCurrentFocus() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 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 */
Alan Viverette48728c22016-04-01 15:00:10 -0400501 public @Nullable View findViewById(@IdRes int id) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 return mWindow.findViewById(id);
503 }
504
505 /**
506 * Set the screen content from a layout resource. The resource will be
507 * inflated, adding all top-level views to the screen.
508 *
509 * @param layoutResID Resource ID to be inflated.
510 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700511 public void setContentView(@LayoutRes int layoutResID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 mWindow.setContentView(layoutResID);
513 }
514
515 /**
516 * Set the screen content to an explicit view. This view is placed
517 * directly into the screen's view hierarchy. It can itself be a complex
Alan Viveretteec186702013-12-05 11:10:31 -0800518 * view hierarchy.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 *
520 * @param view The desired content to display.
521 */
Alan Viverette48728c22016-04-01 15:00:10 -0400522 public void setContentView(@NonNull View view) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 mWindow.setContentView(view);
524 }
525
526 /**
527 * Set the screen content to an explicit view. This view is placed
528 * directly into the screen's view hierarchy. It can itself be a complex
Alan Viverette48728c22016-04-01 15:00:10 -0400529 * view hierarchy.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 *
531 * @param view The desired content to display.
532 * @param params Layout parameters for the view.
533 */
Alan Viverette48728c22016-04-01 15:00:10 -0400534 public void setContentView(@NonNull View view, @Nullable ViewGroup.LayoutParams params) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 mWindow.setContentView(view, params);
536 }
537
538 /**
539 * Add an additional content view to the screen. Added after any existing
540 * ones in the screen -- existing views are NOT removed.
541 *
542 * @param view The desired content to display.
543 * @param params Layout parameters for the view.
544 */
Alan Viverette48728c22016-04-01 15:00:10 -0400545 public void addContentView(@NonNull View view, @Nullable ViewGroup.LayoutParams params) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 mWindow.addContentView(view, params);
547 }
548
549 /**
550 * Set the title text for this dialog's window.
551 *
552 * @param title The new text to display in the title.
553 */
Alan Viverette48728c22016-04-01 15:00:10 -0400554 public void setTitle(@Nullable CharSequence title) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 mWindow.setTitle(title);
556 mWindow.getAttributes().setTitle(title);
557 }
558
559 /**
560 * Set the title text for this dialog's window. The text is retrieved
561 * from the resources with the supplied identifier.
562 *
563 * @param titleId the title's text resource identifier
564 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700565 public void setTitle(@StringRes int titleId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 setTitle(mContext.getText(titleId));
567 }
568
569 /**
570 * A key was pressed down.
571 *
572 * <p>If the focused view didn't want this event, this method is called.
573 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700574 * <p>The default implementation consumed the KEYCODE_BACK to later
575 * handle it in {@link #onKeyUp}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 *
577 * @see #onKeyUp
578 * @see android.view.KeyEvent
579 */
Alan Viverette48728c22016-04-01 15:00:10 -0400580 @Override
581 public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 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 */
Alan Viverette48728c22016-04-01 15:00:10 -0400595 @Override
596 public boolean onKeyLongPress(int keyCode, @NonNull KeyEvent event) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700597 return false;
598 }
599
600 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 * A key was released.
602 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700603 * <p>The default implementation handles KEYCODE_BACK to close the
604 * dialog.
605 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 * @see #onKeyDown
607 * @see KeyEvent
608 */
Alan Viverette48728c22016-04-01 15:00:10 -0400609 @Override
610 public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700611 if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
612 && !event.isCanceled()) {
613 onBackPressed();
614 return true;
615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 return false;
617 }
618
619 /**
620 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
621 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
622 * the event).
623 */
Alan Viverette48728c22016-04-01 15:00:10 -0400624 @Override
625 public boolean onKeyMultiple(int keyCode, int repeatCount, @NonNull KeyEvent event) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 return false;
627 }
628
629 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700630 * Called when the dialog has detected the user's press of the back
631 * key. The default implementation simply cancels the dialog (only if
632 * it is cancelable), but you can override this to do whatever you want.
633 */
634 public void onBackPressed() {
635 if (mCancelable) {
636 cancel();
637 }
638 }
Jeff Brown64da12a2011-01-04 19:57:47 -0800639
640 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +0900641 * Called when a key shortcut event is not handled by any of the views in the Dialog.
Jeff Brown64da12a2011-01-04 19:57:47 -0800642 * Override this method to implement global key shortcuts for the Dialog.
643 * Key shortcuts can also be implemented by setting the
644 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
645 *
646 * @param keyCode The value in event.getKeyCode().
647 * @param event Description of the key event.
648 * @return True if the key shortcut was handled.
649 */
Alan Viverette48728c22016-04-01 15:00:10 -0400650 public boolean onKeyShortcut(int keyCode, @NonNull KeyEvent event) {
Jeff Brown64da12a2011-01-04 19:57:47 -0800651 return false;
652 }
653
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700654 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655 * Called when a touch screen event was not handled by any of the views
656 * under it. This is most useful to process touch events that happen outside
657 * of your window bounds, where there is no view to receive it.
658 *
659 * @param event The touch screen event being processed.
660 * @return Return true if you have consumed the event, false if you haven't.
661 * The default implementation will cancel the dialog when a touch
662 * happens outside of the window bounds.
663 */
Alan Viverette48728c22016-04-01 15:00:10 -0400664 public boolean onTouchEvent(@NonNull MotionEvent event) {
Dianne Hackborncfaf8872011-01-18 13:57:54 -0800665 if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 cancel();
667 return true;
668 }
669
670 return false;
671 }
672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 /**
674 * Called when the trackball was moved and not handled by any of the
675 * views inside of the activity. So, for example, if the trackball moves
676 * while focus is on a button, you will receive a call here because
677 * buttons do not normally do anything with trackball events. The call
678 * here happens <em>before</em> trackball movements are converted to
679 * DPAD key events, which then get sent back to the view hierarchy, and
680 * will be processed at the point for things like focus navigation.
681 *
682 * @param event The trackball event being processed.
683 *
684 * @return Return true if you have consumed the event, false if you haven't.
685 * The default implementation always returns false.
686 */
Alan Viverette48728c22016-04-01 15:00:10 -0400687 public boolean onTrackballEvent(@NonNull MotionEvent event) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 return false;
689 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800690
691 /**
692 * Called when a generic motion event was not handled by any of the
693 * views inside of the dialog.
694 * <p>
Jeff Brown33bbfd22011-02-24 20:55:35 -0800695 * Generic motion events describe joystick movements, mouse hovers, track pad
696 * touches, scroll wheel movements and other input events. The
Jeff Browncb1404e2011-01-15 18:14:15 -0800697 * {@link MotionEvent#getSource() source} of the motion event specifies
698 * the class of input that was received. Implementations of this method
699 * must examine the bits in the source before processing the event.
700 * The following code example shows how this is done.
Jeff Brown33bbfd22011-02-24 20:55:35 -0800701 * </p><p>
702 * Generic motion events with source class
703 * {@link android.view.InputDevice#SOURCE_CLASS_POINTER}
704 * are delivered to the view under the pointer. All other generic motion events are
705 * delivered to the focused view.
706 * </p><p>
707 * See {@link View#onGenericMotionEvent(MotionEvent)} for an example of how to
708 * handle this event.
Jeff Browncb1404e2011-01-15 18:14:15 -0800709 * </p>
Jeff Browncb1404e2011-01-15 18:14:15 -0800710 *
711 * @param event The generic motion event being processed.
712 *
713 * @return Return true if you have consumed the event, false if you haven't.
714 * The default implementation always returns false.
715 */
Alan Viverette48728c22016-04-01 15:00:10 -0400716 public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
Jeff Browncb1404e2011-01-15 18:14:15 -0800717 return false;
718 }
719
Alan Viverette48728c22016-04-01 15:00:10 -0400720 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
722 if (mDecor != null) {
723 mWindowManager.updateViewLayout(mDecor, params);
724 }
725 }
726
Alan Viverette48728c22016-04-01 15:00:10 -0400727 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 public void onContentChanged() {
729 }
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700730
Alan Viverette48728c22016-04-01 15:00:10 -0400731 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 public void onWindowFocusChanged(boolean hasFocus) {
733 }
734
Alan Viverette48728c22016-04-01 15:00:10 -0400735 @Override
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700736 public void onAttachedToWindow() {
737 }
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700738
Alan Viverette48728c22016-04-01 15:00:10 -0400739 @Override
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700740 public void onDetachedFromWindow() {
741 }
Will Haldean Brownca6234e2014-02-12 10:23:41 -0800742
Adam Powell117b6952014-05-05 18:14:56 -0700743 /** @hide */
744 @Override
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700745 public void onWindowDismissed(boolean finishTask) {
Will Haldean Brownca6234e2014-02-12 10:23:41 -0800746 dismiss();
747 }
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 /**
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700750 * Called to process key events. You can override this to intercept all
751 * key events before they are dispatched to the window. Be sure to call
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 * this implementation for key events that should be handled normally.
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700753 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 * @param event The key event.
Wale Ogunwaleba7881c2015-08-01 19:28:29 -0700755 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 * @return boolean Return true if this event was consumed.
757 */
Alan Viverette48728c22016-04-01 15:00:10 -0400758 @Override
759 public boolean dispatchKeyEvent(@NonNull KeyEvent event) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 if ((mOnKeyListener != null) && (mOnKeyListener.onKey(this, event.getKeyCode(), event))) {
761 return true;
762 }
763 if (mWindow.superDispatchKeyEvent(event)) {
764 return true;
765 }
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700766 return event.dispatch(this, mDecor != null
767 ? mDecor.getKeyDispatcherState() : null, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 }
769
770 /**
Jeff Brown64da12a2011-01-04 19:57:47 -0800771 * Called to process a key shortcut event.
772 * You can override this to intercept all key shortcut events before they are
773 * dispatched to the window. Be sure to call this implementation for key shortcut
774 * events that should be handled normally.
775 *
776 * @param event The key shortcut event.
777 * @return True if this event was consumed.
778 */
Alan Viverette48728c22016-04-01 15:00:10 -0400779 @Override
780 public boolean dispatchKeyShortcutEvent(@NonNull KeyEvent event) {
Jeff Brown64da12a2011-01-04 19:57:47 -0800781 if (mWindow.superDispatchKeyShortcutEvent(event)) {
782 return true;
783 }
784 return onKeyShortcut(event.getKeyCode(), event);
785 }
786
787 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 * Called to process touch screen events. You can override this to
789 * intercept all touch screen events before they are dispatched to the
790 * window. Be sure to call this implementation for touch screen events
791 * that should be handled normally.
792 *
793 * @param ev The touch screen event.
794 *
795 * @return boolean Return true if this event was consumed.
796 */
Alan Viverette48728c22016-04-01 15:00:10 -0400797 @Override
798 public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 if (mWindow.superDispatchTouchEvent(ev)) {
800 return true;
801 }
802 return onTouchEvent(ev);
803 }
804
805 /**
806 * Called to process trackball events. You can override this to
807 * intercept all trackball events before they are dispatched to the
808 * window. Be sure to call this implementation for trackball events
809 * that should be handled normally.
810 *
811 * @param ev The trackball event.
812 *
813 * @return boolean Return true if this event was consumed.
814 */
Alan Viverette48728c22016-04-01 15:00:10 -0400815 @Override
816 public boolean dispatchTrackballEvent(@NonNull MotionEvent ev) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 if (mWindow.superDispatchTrackballEvent(ev)) {
818 return true;
819 }
820 return onTrackballEvent(ev);
821 }
822
Jeff Browncb1404e2011-01-15 18:14:15 -0800823 /**
824 * Called to process generic motion events. You can override this to
825 * intercept all generic motion events before they are dispatched to the
826 * window. Be sure to call this implementation for generic motion events
827 * that should be handled normally.
828 *
829 * @param ev The generic motion event.
830 *
831 * @return boolean Return true if this event was consumed.
832 */
Alan Viverette48728c22016-04-01 15:00:10 -0400833 @Override
834 public boolean dispatchGenericMotionEvent(@NonNull MotionEvent ev) {
Jeff Browncb1404e2011-01-15 18:14:15 -0800835 if (mWindow.superDispatchGenericMotionEvent(ev)) {
836 return true;
837 }
838 return onGenericMotionEvent(ev);
839 }
840
Alan Viverette48728c22016-04-01 15:00:10 -0400841 @Override
842 public boolean dispatchPopulateAccessibilityEvent(@NonNull AccessibilityEvent event) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700843 event.setClassName(getClass().getName());
844 event.setPackageName(mContext.getPackageName());
845
846 LayoutParams params = getWindow().getAttributes();
Romain Guy980a9382010-01-08 15:06:28 -0800847 boolean isFullScreen = (params.width == LayoutParams.MATCH_PARENT) &&
848 (params.height == LayoutParams.MATCH_PARENT);
svetoslavganov75986cf2009-05-14 22:28:01 -0700849 event.setFullScreen(isFullScreen);
850
851 return false;
852 }
853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 /**
855 * @see Activity#onCreatePanelView(int)
856 */
Alan Viverette48728c22016-04-01 15:00:10 -0400857 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 public View onCreatePanelView(int featureId) {
859 return null;
860 }
861
862 /**
863 * @see Activity#onCreatePanelMenu(int, Menu)
864 */
Alan Viverette48728c22016-04-01 15:00:10 -0400865 @Override
866 public boolean onCreatePanelMenu(int featureId, @NonNull Menu menu) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 if (featureId == Window.FEATURE_OPTIONS_PANEL) {
868 return onCreateOptionsMenu(menu);
869 }
870
871 return false;
872 }
873
874 /**
875 * @see Activity#onPreparePanel(int, View, Menu)
876 */
Alan Viverette48728c22016-04-01 15:00:10 -0400877 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 public boolean onPreparePanel(int featureId, View view, Menu menu) {
879 if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
Alan Viverette48728c22016-04-01 15:00:10 -0400880 return onPrepareOptionsMenu(menu) && menu.hasVisibleItems();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 }
882 return true;
883 }
884
885 /**
886 * @see Activity#onMenuOpened(int, Menu)
887 */
Alan Viverette48728c22016-04-01 15:00:10 -0400888 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 public boolean onMenuOpened(int featureId, Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800890 if (featureId == Window.FEATURE_ACTION_BAR) {
891 mActionBar.dispatchMenuVisibilityChanged(true);
892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 return true;
894 }
895
896 /**
897 * @see Activity#onMenuItemSelected(int, MenuItem)
898 */
Alan Viverette48728c22016-04-01 15:00:10 -0400899 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 public boolean onMenuItemSelected(int featureId, MenuItem item) {
901 return false;
902 }
903
904 /**
905 * @see Activity#onPanelClosed(int, Menu)
906 */
Alan Viverette48728c22016-04-01 15:00:10 -0400907 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 public void onPanelClosed(int featureId, Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800909 if (featureId == Window.FEATURE_ACTION_BAR) {
910 mActionBar.dispatchMenuVisibilityChanged(false);
911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 }
913
914 /**
915 * It is usually safe to proxy this call to the owner activity's
916 * {@link Activity#onCreateOptionsMenu(Menu)} if the client desires the same
917 * menu for this Dialog.
918 *
919 * @see Activity#onCreateOptionsMenu(Menu)
920 * @see #getOwnerActivity()
921 */
Alan Viverette48728c22016-04-01 15:00:10 -0400922 public boolean onCreateOptionsMenu(@NonNull Menu menu) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 return true;
924 }
925
926 /**
927 * It is usually safe to proxy this call to the owner activity's
928 * {@link Activity#onPrepareOptionsMenu(Menu)} if the client desires the
929 * same menu for this Dialog.
930 *
931 * @see Activity#onPrepareOptionsMenu(Menu)
932 * @see #getOwnerActivity()
933 */
Alan Viverette48728c22016-04-01 15:00:10 -0400934 public boolean onPrepareOptionsMenu(@NonNull Menu menu) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 return true;
936 }
937
938 /**
939 * @see Activity#onOptionsItemSelected(MenuItem)
940 */
Alan Viverette48728c22016-04-01 15:00:10 -0400941 public boolean onOptionsItemSelected(@NonNull MenuItem item) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 return false;
943 }
944
945 /**
946 * @see Activity#onOptionsMenuClosed(Menu)
947 */
Alan Viverette48728c22016-04-01 15:00:10 -0400948 public void onOptionsMenuClosed(@NonNull Menu menu) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 }
950
951 /**
952 * @see Activity#openOptionsMenu()
953 */
954 public void openOptionsMenu() {
Jose Lima7a22fc62015-01-23 17:24:22 -0800955 if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
956 mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 }
Jose Lima7a22fc62015-01-23 17:24:22 -0800959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 /**
961 * @see Activity#closeOptionsMenu()
962 */
963 public void closeOptionsMenu() {
Jose Lima7a22fc62015-01-23 17:24:22 -0800964 if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
965 mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 }
968
969 /**
Adam Powelle67a9dc2010-08-17 17:28:56 -0700970 * @see Activity#invalidateOptionsMenu()
971 */
972 public void invalidateOptionsMenu() {
Jose Lima7a22fc62015-01-23 17:24:22 -0800973 if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
974 mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
975 }
Adam Powelle67a9dc2010-08-17 17:28:56 -0700976 }
977
978 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 * @see Activity#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)
980 */
Alan Viverette48728c22016-04-01 15:00:10 -0400981 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
983 }
984
985 /**
986 * @see Activity#registerForContextMenu(View)
987 */
Alan Viverette48728c22016-04-01 15:00:10 -0400988 public void registerForContextMenu(@NonNull View view) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 view.setOnCreateContextMenuListener(this);
990 }
991
992 /**
993 * @see Activity#unregisterForContextMenu(View)
994 */
Alan Viverette48728c22016-04-01 15:00:10 -0400995 public void unregisterForContextMenu(@NonNull View view) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 view.setOnCreateContextMenuListener(null);
997 }
998
999 /**
1000 * @see Activity#openContextMenu(View)
1001 */
Alan Viverette48728c22016-04-01 15:00:10 -04001002 public void openContextMenu(@NonNull View view) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 view.showContextMenu();
1004 }
1005
1006 /**
1007 * @see Activity#onContextItemSelected(MenuItem)
1008 */
Alan Viverette48728c22016-04-01 15:00:10 -04001009 public boolean onContextItemSelected(@NonNull MenuItem item) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 return false;
1011 }
Clara Bayarri4423d912015-03-02 19:42:48 +00001012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 /**
1014 * @see Activity#onContextMenuClosed(Menu)
1015 */
Alan Viverette48728c22016-04-01 15:00:10 -04001016 public void onContextMenuClosed(@NonNull Menu menu) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 }
Clara Bayarri4423d912015-03-02 19:42:48 +00001018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 /**
1020 * This hook is called when the user signals the desire to start a search.
1021 */
Alan Viverette48728c22016-04-01 15:00:10 -04001022 @Override
1023 public boolean onSearchRequested(@NonNull SearchEvent searchEvent) {
Tim Kilbourn6a975b32015-04-09 17:14:34 -07001024 mSearchEvent = searchEvent;
1025 return onSearchRequested();
1026 }
1027
1028 /**
1029 * This hook is called when the user signals the desire to start a search.
1030 */
Alan Viverette48728c22016-04-01 15:00:10 -04001031 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 public boolean onSearchRequested() {
Karl Rosaen53d24af2009-07-14 14:58:10 -07001033 final SearchManager searchManager = (SearchManager) mContext
1034 .getSystemService(Context.SEARCH_SERVICE);
1035
Bjorn Bringertb8144a92010-02-22 20:48:57 +00001036 // associate search with owner activity
Karl Rosaen7bafed82009-09-04 11:15:21 -07001037 final ComponentName appName = getAssociatedActivity();
lge-aosp06ca9972011-03-15 10:25:57 +09001038 if (appName != null && searchManager.getSearchableInfo(appName) != null) {
Bjorn Bringertb8144a92010-02-22 20:48:57 +00001039 searchManager.startSearch(null, false, appName, null, false);
1040 dismiss();
1041 return true;
1042 } else {
1043 return false;
1044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 }
1046
Clara Bayarri4423d912015-03-02 19:42:48 +00001047 /**
Tim Kilbourn6a975b32015-04-09 17:14:34 -07001048 * During the onSearchRequested() callbacks, this function will return the
1049 * {@link SearchEvent} that triggered the callback, if it exists.
1050 *
1051 * @return SearchEvent The SearchEvent that triggered the {@link
1052 * #onSearchRequested} callback.
1053 */
Alan Viverette48728c22016-04-01 15:00:10 -04001054 public final @Nullable SearchEvent getSearchEvent() {
Tim Kilbourn6a975b32015-04-09 17:14:34 -07001055 return mSearchEvent;
1056 }
1057
Clara Bayarri4423d912015-03-02 19:42:48 +00001058 @Override
Adam Powelldebf3be2010-11-15 18:58:48 -08001059 public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
Clara Bayarri4423d912015-03-02 19:42:48 +00001060 if (mActionBar != null && mActionModeTypeStarting == ActionMode.TYPE_PRIMARY) {
Adam Powelldec9dfd2010-08-09 15:27:54 -07001061 return mActionBar.startActionMode(callback);
1062 }
Adam Powell6e346362010-07-23 10:18:23 -07001063 return null;
1064 }
1065
Clara Bayarri4423d912015-03-02 19:42:48 +00001066 @Override
1067 public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
1068 try {
1069 mActionModeTypeStarting = type;
1070 return onWindowStartingActionMode(callback);
1071 } finally {
1072 mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
1073 }
1074 }
1075
1076 /**
1077 * {@inheritDoc}
Adam Powellcfe9aee2011-11-01 14:56:27 -07001078 *
1079 * Note that if you override this method you should always call through
1080 * to the superclass implementation by calling super.onActionModeStarted(mode).
1081 */
Alan Viverette48728c22016-04-01 15:00:10 -04001082 @Override
Tor Norbyec615c6f2015-03-02 10:11:44 -08001083 @CallSuper
Adam Powelldebf3be2010-11-15 18:58:48 -08001084 public void onActionModeStarted(ActionMode mode) {
Adam Powellcfe9aee2011-11-01 14:56:27 -07001085 mActionMode = mode;
Adam Powelldebf3be2010-11-15 18:58:48 -08001086 }
1087
Adam Powellcfe9aee2011-11-01 14:56:27 -07001088 /**
1089 * {@inheritDoc}
1090 *
1091 * Note that if you override this method you should always call through
1092 * to the superclass implementation by calling super.onActionModeFinished(mode).
1093 */
Alan Viverette48728c22016-04-01 15:00:10 -04001094 @Override
Tor Norbyec615c6f2015-03-02 10:11:44 -08001095 @CallSuper
Adam Powelldebf3be2010-11-15 18:58:48 -08001096 public void onActionModeFinished(ActionMode mode) {
Adam Powellcfe9aee2011-11-01 14:56:27 -07001097 if (mode == mActionMode) {
1098 mActionMode = null;
1099 }
Adam Powelldebf3be2010-11-15 18:58:48 -08001100 }
1101
Karl Rosaen7bafed82009-09-04 11:15:21 -07001102 /**
Adam Powelldec9dfd2010-08-09 15:27:54 -07001103 * @return The activity associated with this dialog, or null if there is no associated activity.
Karl Rosaen7bafed82009-09-04 11:15:21 -07001104 */
1105 private ComponentName getAssociatedActivity() {
1106 Activity activity = mOwnerActivity;
1107 Context context = getContext();
1108 while (activity == null && context != null) {
1109 if (context instanceof Activity) {
1110 activity = (Activity) context; // found it!
1111 } else {
1112 context = (context instanceof ContextWrapper) ?
1113 ((ContextWrapper) context).getBaseContext() : // unwrap one level
1114 null; // done
1115 }
1116 }
1117 return activity == null ? null : activity.getComponentName();
1118 }
1119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120
1121 /**
1122 * Request that key events come to this dialog. Use this if your
1123 * dialog has no views with focus, but the dialog still wants
1124 * a chance to process key events.
1125 *
1126 * @param get true if the dialog should receive key events, false otherwise
1127 * @see android.view.Window#takeKeyEvents
1128 */
1129 public void takeKeyEvents(boolean get) {
1130 mWindow.takeKeyEvents(get);
1131 }
1132
1133 /**
1134 * Enable extended window features. This is a convenience for calling
1135 * {@link android.view.Window#requestFeature getWindow().requestFeature()}.
1136 *
1137 * @param featureId The desired feature as defined in
1138 * {@link android.view.Window}.
1139 * @return Returns true if the requested feature is supported and now
1140 * enabled.
1141 *
1142 * @see android.view.Window#requestFeature
1143 */
1144 public final boolean requestWindowFeature(int featureId) {
1145 return getWindow().requestFeature(featureId);
1146 }
1147
1148 /**
1149 * Convenience for calling
1150 * {@link android.view.Window#setFeatureDrawableResource}.
1151 */
Tor Norbye7b9c9122013-05-30 16:48:33 -07001152 public final void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 getWindow().setFeatureDrawableResource(featureId, resId);
1154 }
1155
1156 /**
1157 * Convenience for calling
1158 * {@link android.view.Window#setFeatureDrawableUri}.
1159 */
Alan Viverette48728c22016-04-01 15:00:10 -04001160 public final void setFeatureDrawableUri(int featureId, @Nullable Uri uri) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 getWindow().setFeatureDrawableUri(featureId, uri);
1162 }
1163
1164 /**
1165 * Convenience for calling
1166 * {@link android.view.Window#setFeatureDrawable(int, Drawable)}.
1167 */
Alan Viverette48728c22016-04-01 15:00:10 -04001168 public final void setFeatureDrawable(int featureId, @Nullable Drawable drawable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 getWindow().setFeatureDrawable(featureId, drawable);
1170 }
1171
1172 /**
1173 * Convenience for calling
1174 * {@link android.view.Window#setFeatureDrawableAlpha}.
1175 */
1176 public final void setFeatureDrawableAlpha(int featureId, int alpha) {
1177 getWindow().setFeatureDrawableAlpha(featureId, alpha);
1178 }
1179
Alan Viverette48728c22016-04-01 15:00:10 -04001180 public @NonNull LayoutInflater getLayoutInflater() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 return getWindow().getLayoutInflater();
1182 }
1183
1184 /**
1185 * Sets whether this dialog is cancelable with the
1186 * {@link KeyEvent#KEYCODE_BACK BACK} key.
1187 */
1188 public void setCancelable(boolean flag) {
1189 mCancelable = flag;
1190 }
1191
1192 /**
1193 * Sets whether this dialog is canceled when touched outside the window's
1194 * bounds. If setting to true, the dialog is set to be cancelable if not
1195 * already set.
1196 *
1197 * @param cancel Whether the dialog should be canceled when touched outside
1198 * the window.
1199 */
1200 public void setCanceledOnTouchOutside(boolean cancel) {
1201 if (cancel && !mCancelable) {
1202 mCancelable = true;
1203 }
1204
Dianne Hackborncfaf8872011-01-18 13:57:54 -08001205 mWindow.setCloseOnTouchOutside(cancel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 }
1207
1208 /**
1209 * Cancel the dialog. This is essentially the same as calling {@link #dismiss()}, but it will
1210 * also call your {@link DialogInterface.OnCancelListener} (if registered).
1211 */
Alan Viverette48728c22016-04-01 15:00:10 -04001212 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 public void cancel() {
Dianne Hackborn8b4cac12011-01-03 13:58:14 -08001214 if (!mCanceled && mCancelMessage != null) {
1215 mCanceled = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 // Obtain a new message so this dialog can be re-used
1217 Message.obtain(mCancelMessage).sendToTarget();
1218 }
1219 dismiss();
1220 }
1221
1222 /**
1223 * Set a listener to be invoked when the dialog is canceled.
Adam Powell7f02dc52012-08-27 13:35:16 -07001224 *
1225 * <p>This will only be invoked when the dialog is canceled.
1226 * Cancel events alone will not capture all ways that
1227 * the dialog might be dismissed. If the creator needs
1228 * to know when a dialog is dismissed in general, use
1229 * {@link #setOnDismissListener}.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 *
1231 * @param listener The {@link DialogInterface.OnCancelListener} to use.
1232 */
Alan Viverette48728c22016-04-01 15:00:10 -04001233 public void setOnCancelListener(@Nullable OnCancelListener listener) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001234 if (mCancelAndDismissTaken != null) {
1235 throw new IllegalStateException(
1236 "OnCancelListener is already taken by "
1237 + mCancelAndDismissTaken + " and can not be replaced.");
1238 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 if (listener != null) {
Romain Guy045163a2009-07-14 13:59:33 -07001240 mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 } else {
1242 mCancelMessage = null;
1243 }
1244 }
1245
1246 /**
1247 * Set a message to be sent when the dialog is canceled.
1248 * @param msg The msg to send when the dialog is canceled.
1249 * @see #setOnCancelListener(android.content.DialogInterface.OnCancelListener)
1250 */
Alan Viverette48728c22016-04-01 15:00:10 -04001251 public void setCancelMessage(@Nullable Message msg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 mCancelMessage = msg;
1253 }
1254
1255 /**
1256 * Set a listener to be invoked when the dialog is dismissed.
1257 * @param listener The {@link DialogInterface.OnDismissListener} to use.
1258 */
Alan Viverette48728c22016-04-01 15:00:10 -04001259 public void setOnDismissListener(@Nullable OnDismissListener listener) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001260 if (mCancelAndDismissTaken != null) {
1261 throw new IllegalStateException(
1262 "OnDismissListener is already taken by "
1263 + mCancelAndDismissTaken + " and can not be replaced.");
1264 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 if (listener != null) {
Romain Guy045163a2009-07-14 13:59:33 -07001266 mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 } else {
1268 mDismissMessage = null;
1269 }
1270 }
1271
1272 /**
Romain Guy045163a2009-07-14 13:59:33 -07001273 * Sets a listener to be invoked when the dialog is shown.
Ficus Kirkpatrick130a8b72010-01-14 15:39:43 -08001274 * @param listener The {@link DialogInterface.OnShowListener} to use.
Romain Guy045163a2009-07-14 13:59:33 -07001275 */
Alan Viverette48728c22016-04-01 15:00:10 -04001276 public void setOnShowListener(@Nullable OnShowListener listener) {
Romain Guy045163a2009-07-14 13:59:33 -07001277 if (listener != null) {
1278 mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
1279 } else {
1280 mShowMessage = null;
1281 }
1282 }
1283
1284 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 * Set a message to be sent when the dialog is dismissed.
1286 * @param msg The msg to send when the dialog is dismissed.
1287 */
Alan Viverette48728c22016-04-01 15:00:10 -04001288 public void setDismissMessage(@Nullable Message msg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 mDismissMessage = msg;
1290 }
1291
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001292 /** @hide */
Alan Viverette48728c22016-04-01 15:00:10 -04001293 public boolean takeCancelAndDismissListeners(@Nullable String msg,
1294 @Nullable OnCancelListener cancel, @Nullable OnDismissListener dismiss) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001295 if (mCancelAndDismissTaken != null) {
1296 mCancelAndDismissTaken = null;
1297 } else if (mCancelMessage != null || mDismissMessage != null) {
1298 return false;
1299 }
1300
1301 setOnCancelListener(cancel);
1302 setOnDismissListener(dismiss);
1303 mCancelAndDismissTaken = msg;
1304
1305 return true;
1306 }
1307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 /**
1309 * By default, this will use the owner Activity's suggested stream type.
1310 *
1311 * @see Activity#setVolumeControlStream(int)
1312 * @see #setOwnerActivity(Activity)
1313 */
1314 public final void setVolumeControlStream(int streamType) {
1315 getWindow().setVolumeControlStream(streamType);
1316 }
1317
1318 /**
1319 * @see Activity#getVolumeControlStream()
1320 */
1321 public final int getVolumeControlStream() {
1322 return getWindow().getVolumeControlStream();
1323 }
1324
1325 /**
1326 * Sets the callback that will be called if a key is dispatched to the dialog.
1327 */
Alan Viverette48728c22016-04-01 15:00:10 -04001328 public void setOnKeyListener(@Nullable OnKeyListener onKeyListener) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 mOnKeyListener = onKeyListener;
1330 }
1331
Romain Guy045163a2009-07-14 13:59:33 -07001332 private static final class ListenersHandler extends Handler {
Alan Viverette48728c22016-04-01 15:00:10 -04001333 private final WeakReference<DialogInterface> mDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334
Romain Guy045163a2009-07-14 13:59:33 -07001335 public ListenersHandler(Dialog dialog) {
Alan Viverette48728c22016-04-01 15:00:10 -04001336 mDialog = new WeakReference<>(dialog);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 }
1338
1339 @Override
1340 public void handleMessage(Message msg) {
1341 switch (msg.what) {
1342 case DISMISS:
1343 ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
1344 break;
1345 case CANCEL:
1346 ((OnCancelListener) msg.obj).onCancel(mDialog.get());
1347 break;
Romain Guy045163a2009-07-14 13:59:33 -07001348 case SHOW:
1349 ((OnShowListener) msg.obj).onShow(mDialog.get());
1350 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 }
1352 }
1353 }
1354}