ActionMenuItemView.java revision 49c78900da0d43140fb602431fb93212bd7f6c70
1bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/* 2bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Copyright (C) 2010 The Android Open Source Project 3bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * 4bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * you may not use this file except in compliance with the License. 6bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * You may obtain a copy of the License at 7bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * 8bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 9bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * 10bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Unless required by applicable law or agreed to in writing, software 11bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * See the License for the specific language governing permissions and 14bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * limitations under the License. 15bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */ 16bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 17da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.view.menu; 18bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 19bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Context; 2049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.content.res.Configuration; 21bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.Resources; 22bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.TypedArray; 23bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.graphics.Rect; 24bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.graphics.drawable.Drawable; 2549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.os.Build; 2649c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.GravityCompat; 27da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R; 2889208232f3b5d1451408d787872504a190bc7ee0Chris Banesimport android.support.v7.internal.widget.CompatTextView; 2949c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.ActionMenuView; 3049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.ListPopupWindow; 31bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.text.TextUtils; 3230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.text.method.TransformationMethod; 33bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.util.AttributeSet; 34bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.Gravity; 3549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.MotionEvent; 36bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View; 37bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.Toast; 38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 3930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport java.util.Locale; 4030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell 41bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/** 42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * @hide 43bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */ 4489208232f3b5d1451408d787872504a190bc7ee0Chris Banespublic class ActionMenuItemView extends CompatTextView 4520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener, 4620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns ActionMenuView.ActionMenuChildView { 4720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 48ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private static final String TAG = "ActionMenuItemView"; 49ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 50ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private MenuItemImpl mItemData; 51ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private CharSequence mTitle; 52ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private Drawable mIcon; 53ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private MenuBuilder.ItemInvoker mItemInvoker; 5449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private ListPopupWindow.ForwardingListener mForwardingListener; 5549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private PopupCallback mPopupCallback; 56ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 57ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private boolean mAllowTextWithIcon; 58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private boolean mExpandedFormat; 59ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private int mMinWidth; 60ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private int mSavedPaddingLeft; 61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 6249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private static final int MAX_ICON_SIZE = 32; // dp 6349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mMaxIconSize; 6449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public ActionMenuItemView(Context context) { 66ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani this(context, null); 67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 68ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public ActionMenuItemView(Context context, AttributeSet attrs) { 70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani this(context, attrs, 0); 71ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 72ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 73ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public ActionMenuItemView(Context context, AttributeSet attrs, int defStyle) { 74ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super(context, attrs, defStyle); 75ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final Resources res = context.getResources(); 76ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAllowTextWithIcon = res.getBoolean( 7749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes R.bool.abc_config_allowActionMenuItemTextWithIcon); 78ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani TypedArray a = context.obtainStyledAttributes(attrs, 7949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes R.styleable.ActionMenuItemView, defStyle, 0); 80ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMinWidth = a.getDimensionPixelSize( 8120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns R.styleable.ActionMenuItemView_android_minWidth, 0); 82ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani a.recycle(); 83ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 8449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final float density = res.getDisplayMetrics().density; 8549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mMaxIconSize = (int) (MAX_ICON_SIZE * density + 0.5f); 8649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 87ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setOnClickListener(this); 88ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setOnLongClickListener(this); 89ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 9030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell setTransformationMethod(new AllCapsTransformationMethod()); 9130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell 92ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mSavedPaddingLeft = -1; 93ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 94ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 9549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void onConfigurationChanged(Configuration newConfig) { 9649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (Build.VERSION.SDK_INT >= 8) { 9749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super.onConfigurationChanged(newConfig); 9849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 9949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 10049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mAllowTextWithIcon = getContext().getResources().getBoolean( 10149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes R.bool.abc_config_allowActionMenuItemTextWithIcon); 10249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes updateTextButtonVisibility(); 10349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 10449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setPadding(int l, int t, int r, int b) { 107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mSavedPaddingLeft = l; 108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super.setPadding(l, t, r, b); 109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuItemImpl getItemData() { 112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return mItemData; 113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void initialize(MenuItemImpl itemData, int menuType) { 116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mItemData = itemData; 117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setIcon(itemData.getIcon()); 119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon 120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setId(itemData.getItemId()); 121ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 122ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE); 123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setEnabled(itemData.isEnabled()); 12449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (itemData.hasSubMenu()) { 12549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mForwardingListener == null) { 12649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mForwardingListener = new ActionMenuItemForwardingListener(); 12749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 12849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 13149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 13249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean onTouchEvent(MotionEvent e) { 13349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mItemData.hasSubMenu() && mForwardingListener != null 13449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes && mForwardingListener.onTouch(this, e)) { 13549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return true; 13649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 13749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return super.onTouchEvent(e); 13849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 13949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 14049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onClick(View v) { 142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mItemInvoker != null) { 143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mItemInvoker.invokeItem(mItemData); 144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setItemInvoker(MenuBuilder.ItemInvoker invoker) { 14820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mItemInvoker = invoker; 149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 15149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setPopupCallback(PopupCallback popupCallback) { 15249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopupCallback = popupCallback; 15349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 15449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean prefersCondensedTitle() { 156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setCheckable(boolean checkable) { 160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // TODO Support checkable action items 161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setChecked(boolean checked) { 164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // TODO Support checkable action items 165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setExpandedFormat(boolean expandedFormat) { 168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mExpandedFormat != expandedFormat) { 169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mExpandedFormat = expandedFormat; 170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mItemData != null) { 171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mItemData.actionFormatChanged(); 172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private void updateTextButtonVisibility() { 177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani boolean visible = !TextUtils.isEmpty(mTitle); 178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani visible &= mIcon == null || 17920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat)); 180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setText(visible ? mTitle : null); 182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setIcon(Drawable icon) { 185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mIcon = icon; 18649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (icon != null) { 18749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int width = icon.getIntrinsicWidth(); 18849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int height = icon.getIntrinsicHeight(); 18949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (width > mMaxIconSize) { 19049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final float scale = (float) mMaxIconSize / width; 19149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes width = mMaxIconSize; 19249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes height *= scale; 19349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 19449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (height > mMaxIconSize) { 19549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final float scale = (float) mMaxIconSize / height; 19649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes height = mMaxIconSize; 19749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes width *= scale; 19849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 19949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes icon.setBounds(0, 0, width, height); 20049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 20149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes setCompoundDrawables(icon, null, null, null); 202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani updateTextButtonVisibility(); 204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean hasText() { 207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return !TextUtils.isEmpty(getText()); 208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setShortcut(boolean showShortcut, char shortcutKey) { 211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Action buttons don't show text for shortcut keys. 212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setTitle(CharSequence title) { 215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTitle = title; 216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani setContentDescription(mTitle); 218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani updateTextButtonVisibility(); 219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean showsIcon() { 222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean needsDividerBefore() { 226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return hasText() && mItemData.getIcon() == null; 227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean needsDividerAfter() { 230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return hasText(); 231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean onLongClick(View v) { 235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (hasText()) { 236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Don't show the cheat sheet for items that already show text. 237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int[] screenPos = new int[2]; 241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final Rect displayFrame = new Rect(); 242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani getLocationOnScreen(screenPos); 243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani getWindowVisibleDisplayFrame(displayFrame); 244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final Context context = getContext(); 246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int width = getWidth(); 247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int height = getHeight(); 248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int midy = screenPos[1] + height / 2; 249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int screenWidth = context.getResources().getDisplayMetrics().widthPixels; 250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT); 252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (midy < displayFrame.height()) { 253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Show along the top; follow action buttons 25449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes cheatSheet.setGravity(Gravity.TOP | GravityCompat.END, 25520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns screenWidth - screenPos[0] - width / 2, height); 256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } else { 257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Show along the bottom center 258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height); 259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani cheatSheet.show(); 261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final boolean textVisible = hasText(); 267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (textVisible && mSavedPaddingLeft >= 0) { 268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super.setPadding(mSavedPaddingLeft, getPaddingTop(), 26920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns getPaddingRight(), getPaddingBottom()); 270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super.onMeasure(widthMeasureSpec, heightMeasureSpec); 273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int oldMeasuredWidth = getMeasuredWidth(); 277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(widthSize, mMinWidth) 27820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns : mMinWidth; 279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (widthMode != MeasureSpec.EXACTLY && mMinWidth > 0 && oldMeasuredWidth < targetWidth) { 281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Remeasure at exactly the minimum width. 282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super.onMeasure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), 28320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns heightMeasureSpec); 284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (!textVisible && mIcon != null) { 287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // TextView won't center compound drawables in both dimensions without 288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // a little coercion. Pad in to center the icon after we've measured. 289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int w = getMeasuredWidth(); 29049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int dw = mIcon.getBounds().width(); 291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super.setPadding((w - dw) / 2, getPaddingTop(), getPaddingRight(), getPaddingBottom()); 292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 29430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell 29549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private class ActionMenuItemForwardingListener extends ListPopupWindow.ForwardingListener { 29649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public ActionMenuItemForwardingListener() { 29749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(ActionMenuItemView.this); 29849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 29949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 30049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 30149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public ListPopupWindow getPopup() { 30249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mPopupCallback != null) { 30349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPopupCallback.getPopup(); 30449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 30549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return null; 30649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 30749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 30849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 30949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected boolean onForwardingStarted() { 31049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Call the invoker, then check if the expected popup is showing. 31149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mItemInvoker != null && mItemInvoker.invokeItem(mItemData)) { 31249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final ListPopupWindow popup = getPopup(); 31349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return popup != null && popup.isShowing(); 31449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 31549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return false; 31649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 31749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 31849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 31949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes protected boolean onForwardingStopped() { 32049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final ListPopupWindow popup = getPopup(); 32149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (popup != null) { 32249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes popup.dismiss(); 32349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return true; 32449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 32549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return false; 32649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 32749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 32849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 32930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell private class AllCapsTransformationMethod implements TransformationMethod { 33030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell private Locale mLocale; 33130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell 33230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell public AllCapsTransformationMethod() { 33330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell mLocale = getContext().getResources().getConfiguration().locale; 33430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell } 33530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell 33630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell @Override 33730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell public CharSequence getTransformation(CharSequence source, View view) { 33830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell return source != null ? source.toString().toUpperCase(mLocale) : null; 33930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell } 34030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell 34130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell @Override 34230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell public void onFocusChanged(View view, CharSequence sourceText, boolean focused, 34330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell int direction, Rect previouslyFocusedRect) { 34430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell } 34530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell } 34649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 34749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static abstract class PopupCallback { 34849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public abstract ListPopupWindow getPopup(); 34949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 350bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell} 351