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