ActionMenuView.java revision f75eeb28def26798682748aa5dedabebac86bb6a
1/* 2 * Copyright (C) 2010 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 */ 16package com.android.internal.view.menu; 17 18import android.content.Context; 19import android.content.res.Configuration; 20import android.content.res.Resources; 21import android.content.res.TypedArray; 22import android.util.AttributeSet; 23import android.view.ViewGroup; 24import android.widget.ImageButton; 25import android.widget.LinearLayout; 26 27import java.lang.ref.WeakReference; 28import java.util.ArrayList; 29 30/** 31 * @hide 32 */ 33public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView { 34 private static final String TAG = "ActionMenuView"; 35 36 private MenuBuilder mMenu; 37 38 private int mItemPadding; 39 private int mItemMargin; 40 private int mMaxItems; 41 private boolean mReserveOverflow; 42 private OverflowMenuButton mOverflowButton; 43 private WeakReference<MenuPopupHelper> mOverflowPopup; 44 45 public ActionMenuView(Context context) { 46 this(context, null); 47 } 48 49 public ActionMenuView(Context context, AttributeSet attrs) { 50 super(context, attrs); 51 52 TypedArray a = context.obtainStyledAttributes(attrs, 53 com.android.internal.R.styleable.Theme); 54 mItemPadding = a.getDimensionPixelOffset( 55 com.android.internal.R.styleable.Theme_actionButtonPadding, 0); 56 mItemMargin = mItemPadding / 2; 57 a.recycle(); 58 59 final Resources res = getResources(); 60 final int size = res.getDimensionPixelSize(com.android.internal.R.dimen.action_icon_size); 61 final int spaceAvailable = res.getDisplayMetrics().widthPixels / 2; 62 final int itemSpace = size + mItemPadding; 63 64 mMaxItems = spaceAvailable / (itemSpace > 0 ? itemSpace : 1); 65 66 // TODO There has to be a better way to indicate that we don't have a hard menu key. 67 final int screen = res.getConfiguration().screenLayout; 68 mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) == 69 Configuration.SCREENLAYOUT_SIZE_XLARGE; 70 } 71 72 public boolean isOverflowReserved() { 73 return mReserveOverflow; 74 } 75 76 public void setOverflowReserved(boolean reserveOverflow) { 77 mReserveOverflow = reserveOverflow; 78 } 79 80 @Override 81 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 82 if (p instanceof LayoutParams) { 83 LayoutParams lp = (LayoutParams) p; 84 return lp.leftMargin == mItemMargin && lp.rightMargin == mItemMargin && 85 lp.width == LayoutParams.WRAP_CONTENT && lp.height == LayoutParams.WRAP_CONTENT; 86 } 87 return false; 88 } 89 90 @Override 91 protected LayoutParams generateDefaultLayoutParams() { 92 LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, 93 LayoutParams.WRAP_CONTENT); 94 params.leftMargin = mItemMargin; 95 params.rightMargin = mItemMargin; 96 return params; 97 } 98 99 @Override 100 protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 101 return generateDefaultLayoutParams(); 102 } 103 104 public int getItemMargin() { 105 return mItemMargin; 106 } 107 108 public boolean invokeItem(MenuItemImpl item) { 109 return mMenu.performItemAction(item, 0); 110 } 111 112 public int getWindowAnimations() { 113 return 0; 114 } 115 116 public void initialize(MenuBuilder menu, int menuType) { 117 menu.setMaxActionItems(mMaxItems); 118 mMenu = menu; 119 updateChildren(true); 120 } 121 122 public void updateChildren(boolean cleared) { 123 final boolean reserveOverflow = mReserveOverflow; 124 removeAllViews(); 125 126 final ArrayList<MenuItemImpl> itemsToShow = mMenu.getActionItems(reserveOverflow); 127 final int itemCount = itemsToShow.size(); 128 129 for (int i = 0; i < itemCount; i++) { 130 final MenuItemImpl itemData = itemsToShow.get(i); 131 addItemView((ActionMenuItemView) itemData.getItemView(MenuBuilder.TYPE_ACTION_BUTTON, 132 this)); 133 } 134 135 if (reserveOverflow) { 136 if (mMenu.getNonActionItems(true).size() > 0) { 137 OverflowMenuButton button = new OverflowMenuButton(mContext); 138 addView(button); 139 mOverflowButton = button; 140 } else { 141 mOverflowButton = null; 142 } 143 } 144 } 145 146 public boolean showOverflowMenu() { 147 if (mOverflowButton != null) { 148 MenuPopupHelper popup = new MenuPopupHelper(getContext(), mMenu, mOverflowButton, true); 149 popup.show(); 150 mOverflowPopup = new WeakReference<MenuPopupHelper>(popup); 151 return true; 152 } 153 return false; 154 } 155 156 public boolean hideOverflowMenu() { 157 MenuPopupHelper popup = mOverflowPopup != null ? mOverflowPopup.get() : null; 158 if (popup != null) { 159 popup.dismiss(); 160 return true; 161 } 162 return false; 163 } 164 165 private void addItemView(ActionMenuItemView view) { 166 view.setItemInvoker(this); 167 addView(view); 168 } 169 170 private class OverflowMenuButton extends ImageButton { 171 public OverflowMenuButton(Context context) { 172 super(context, null, com.android.internal.R.attr.actionButtonStyle); 173 174 final Resources res = context.getResources(); 175 setClickable(true); 176 setFocusable(true); 177 // TODO setTitle() to a localized string for accessibility 178 setImageDrawable(res.getDrawable(com.android.internal.R.drawable.ic_menu_more)); 179 setVisibility(VISIBLE); 180 setEnabled(true); 181 } 182 183 @Override 184 public boolean performClick() { 185 if (super.performClick()) { 186 return true; 187 } 188 189 showOverflowMenu(); 190 return true; 191 } 192 } 193} 194