MenuDialogHelper.java revision 8262949c1a6b7e191020b31fc914972bb0b58ab0
18262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns/* 28262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Copyright (C) 2013 The Android Open Source Project 38262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * 48262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Licensed under the Apache License, Version 2.0 (the "License"); 58262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * you may not use this file except in compliance with the License. 68262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * You may obtain a copy of the License at 78262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * 88262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * http://www.apache.org/licenses/LICENSE-2.0 98262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * 108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Unless required by applicable law or agreed to in writing, software 118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * distributed under the License is distributed on an "AS IS" BASIS, 128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * See the License for the specific language governing permissions and 148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * limitations under the License. 158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */ 168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 178262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnspackage android.support.appcompat.view.menu; 188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.app.AlertDialog; 208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.app.Dialog; 218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.content.DialogInterface; 228262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.os.IBinder; 238262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.support.appcompat.R; 248262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.KeyEvent; 258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.View; 268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.Window; 278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.WindowManager; 288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns/** 308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Helper for menus that appear as Dialogs (context and submenus). 318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * 328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * @hide 338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */ 348262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnspublic class MenuDialogHelper implements DialogInterface.OnKeyListener, 358262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns DialogInterface.OnClickListener, 368262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns DialogInterface.OnDismissListener, 378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns MenuPresenter.Callback { 388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns private MenuBuilder mMenu; 398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns private AlertDialog mDialog; 408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns ListMenuPresenter mPresenter; 418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns private MenuPresenter.Callback mPresenterCallback; 428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public MenuDialogHelper(MenuBuilder menu) { 448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mMenu = menu; 458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns /** 488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Shows menu as a dialog. 498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * 508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * @param windowToken Optional token to assign to the window. 518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */ 528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void show(IBinder windowToken) { 538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Many references to mMenu, create local reference 548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns final MenuBuilder menu = mMenu; 558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Get the builder for the dialog 578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns final AlertDialog.Builder builder = new AlertDialog.Builder(menu.getContext()); 588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenter = new ListMenuPresenter(builder.getContext(), 608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns R.layout.list_menu_item_layout); 618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenter.setCallback(this); 638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mMenu.addMenuPresenter(mPresenter); 648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns builder.setAdapter(mPresenter.getAdapter(), this); 658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Set the title 678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns final View headerView = menu.getHeaderView(); 688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (headerView != null) { 698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Menu's client has given a custom header view, use it 708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns builder.setCustomTitle(headerView); 718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } else { 728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Otherwise use the (text) title and icon 738262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns builder.setIcon(menu.getHeaderIcon()).setTitle(menu.getHeaderTitle()); 748262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 758262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 768262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Set the key listener 778262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns builder.setOnKeyListener(this); 788262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 798262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Show the menu 808262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mDialog = builder.create(); 818262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mDialog.setOnDismissListener(this); 828262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 838262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes(); 848262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 858262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (windowToken != null) { 868262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns lp.token = windowToken; 878262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 888262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 898262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 908262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mDialog.show(); 918262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 928262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 938262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 948262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK) { 958262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (event.getAction() == KeyEvent.ACTION_DOWN 968262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns && event.getRepeatCount() == 0) { 978262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns Window win = mDialog.getWindow(); 988262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (win != null) { 998262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns View decor = win.getDecorView(); 1008262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (decor != null) { 1018262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns KeyEvent.DispatcherState ds = decor.getKeyDispatcherState(); 1028262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (ds != null) { 1038262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns ds.startTracking(event, this); 1048262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return true; 1058262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1068262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1078262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1088262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()) { 1098262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns Window win = mDialog.getWindow(); 1108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (win != null) { 1118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns View decor = win.getDecorView(); 1128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (decor != null) { 1138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns KeyEvent.DispatcherState ds = decor.getKeyDispatcherState(); 1148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (ds != null && ds.isTracking(event)) { 1158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mMenu.close(true); 1168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns dialog.dismiss(); 1178262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return true; 1188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1228262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1238262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1248262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Menu shortcut matching 1258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return mMenu.performShortcut(keyCode, event, 0); 1268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void setPresenterCallback(MenuPresenter.Callback cb) { 1308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenterCallback = cb; 1318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns /** 1348262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Dismisses the menu's dialog. 1358262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * 1368262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * @see Dialog#dismiss() 1378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */ 1388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void dismiss() { 1398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (mDialog != null) { 1408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mDialog.dismiss(); 1418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns @Override 1458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void onDismiss(DialogInterface dialog) { 1468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenter.onCloseMenu(mMenu, true); 1478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns @Override 1508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 1518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (allMenusAreClosing || menu == mMenu) { 1528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns dismiss(); 1538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (mPresenterCallback != null) { 1558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); 1568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns @Override 1608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public boolean onOpenSubMenu(MenuBuilder subMenu) { 1618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (mPresenterCallback != null) { 1628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return mPresenterCallback.onOpenSubMenu(subMenu); 1638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return false; 1658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void onClick(DialogInterface dialog, int which) { 1688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mMenu.performItemAction((MenuItemImpl) mPresenter.getAdapter().getItem(which), 0); 1698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns} 171