1/* 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.support.v7.view.menu; 18 19import android.content.Context; 20import android.graphics.drawable.Drawable; 21import android.support.v7.appcompat.R; 22import android.support.v7.widget.TintTypedArray; 23import android.util.AttributeSet; 24import android.view.LayoutInflater; 25import android.view.View; 26import android.view.ViewGroup; 27import android.widget.CheckBox; 28import android.widget.CompoundButton; 29import android.widget.ImageView; 30import android.widget.LinearLayout; 31import android.widget.RadioButton; 32import android.widget.TextView; 33 34/** 35 * The item view for each item in the ListView-based MenuViews. 36 * 37 * @hide 38 */ 39public class ListMenuItemView extends LinearLayout implements MenuView.ItemView { 40 private static final String TAG = "ListMenuItemView"; 41 private MenuItemImpl mItemData; 42 43 private ImageView mIconView; 44 private RadioButton mRadioButton; 45 private TextView mTitleView; 46 private CheckBox mCheckBox; 47 private TextView mShortcutView; 48 private ImageView mSubMenuArrowView; 49 50 private Drawable mBackground; 51 private int mTextAppearance; 52 private Context mTextAppearanceContext; 53 private boolean mPreserveIconSpacing; 54 private Drawable mSubMenuArrow; 55 56 private int mMenuType; 57 58 private LayoutInflater mInflater; 59 60 private boolean mForceShowIcon; 61 62 public ListMenuItemView(Context context, AttributeSet attrs) { 63 this(context, attrs, R.attr.listMenuViewStyle); 64 } 65 66 public ListMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) { 67 super(context, attrs); 68 69 final TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), 70 attrs, R.styleable.MenuView, defStyleAttr, 0); 71 72 mBackground = a.getDrawable(R.styleable.MenuView_android_itemBackground); 73 mTextAppearance = a.getResourceId(R.styleable. 74 MenuView_android_itemTextAppearance, -1); 75 mPreserveIconSpacing = a.getBoolean( 76 R.styleable.MenuView_preserveIconSpacing, false); 77 mTextAppearanceContext = context; 78 mSubMenuArrow = a.getDrawable(R.styleable.MenuView_subMenuArrow); 79 80 a.recycle(); 81 } 82 83 @Override 84 protected void onFinishInflate() { 85 super.onFinishInflate(); 86 87 setBackgroundDrawable(mBackground); 88 89 mTitleView = (TextView) findViewById(R.id.title); 90 if (mTextAppearance != -1) { 91 mTitleView.setTextAppearance(mTextAppearanceContext, 92 mTextAppearance); 93 } 94 95 mShortcutView = (TextView) findViewById(R.id.shortcut); 96 mSubMenuArrowView = (ImageView) findViewById(R.id.submenuarrow); 97 if (mSubMenuArrowView != null) { 98 mSubMenuArrowView.setImageDrawable(mSubMenuArrow); 99 } 100 } 101 102 public void initialize(MenuItemImpl itemData, int menuType) { 103 mItemData = itemData; 104 mMenuType = menuType; 105 106 setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE); 107 108 setTitle(itemData.getTitleForItemView(this)); 109 setCheckable(itemData.isCheckable()); 110 setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut()); 111 setIcon(itemData.getIcon()); 112 setEnabled(itemData.isEnabled()); 113 setSubMenuArrowVisible(itemData.hasSubMenu()); 114 } 115 116 public void setForceShowIcon(boolean forceShow) { 117 mPreserveIconSpacing = mForceShowIcon = forceShow; 118 } 119 120 public void setTitle(CharSequence title) { 121 if (title != null) { 122 mTitleView.setText(title); 123 124 if (mTitleView.getVisibility() != VISIBLE) mTitleView.setVisibility(VISIBLE); 125 } else { 126 if (mTitleView.getVisibility() != GONE) mTitleView.setVisibility(GONE); 127 } 128 } 129 130 public MenuItemImpl getItemData() { 131 return mItemData; 132 } 133 134 public void setCheckable(boolean checkable) { 135 if (!checkable && mRadioButton == null && mCheckBox == null) { 136 return; 137 } 138 139 // Depending on whether its exclusive check or not, the checkbox or 140 // radio button will be the one in use (and the other will be otherCompoundButton) 141 final CompoundButton compoundButton; 142 final CompoundButton otherCompoundButton; 143 144 if (mItemData.isExclusiveCheckable()) { 145 if (mRadioButton == null) { 146 insertRadioButton(); 147 } 148 compoundButton = mRadioButton; 149 otherCompoundButton = mCheckBox; 150 } else { 151 if (mCheckBox == null) { 152 insertCheckBox(); 153 } 154 compoundButton = mCheckBox; 155 otherCompoundButton = mRadioButton; 156 } 157 158 if (checkable) { 159 compoundButton.setChecked(mItemData.isChecked()); 160 161 final int newVisibility = checkable ? VISIBLE : GONE; 162 if (compoundButton.getVisibility() != newVisibility) { 163 compoundButton.setVisibility(newVisibility); 164 } 165 166 // Make sure the other compound button isn't visible 167 if (otherCompoundButton != null && otherCompoundButton.getVisibility() != GONE) { 168 otherCompoundButton.setVisibility(GONE); 169 } 170 } else { 171 if (mCheckBox != null) { 172 mCheckBox.setVisibility(GONE); 173 } 174 if (mRadioButton != null) { 175 mRadioButton.setVisibility(GONE); 176 } 177 } 178 } 179 180 public void setChecked(boolean checked) { 181 CompoundButton compoundButton; 182 183 if (mItemData.isExclusiveCheckable()) { 184 if (mRadioButton == null) { 185 insertRadioButton(); 186 } 187 compoundButton = mRadioButton; 188 } else { 189 if (mCheckBox == null) { 190 insertCheckBox(); 191 } 192 compoundButton = mCheckBox; 193 } 194 195 compoundButton.setChecked(checked); 196 } 197 198 private void setSubMenuArrowVisible(boolean hasSubmenu) { 199 if (mSubMenuArrowView != null) { 200 mSubMenuArrowView.setVisibility(hasSubmenu ? View.VISIBLE : View.GONE); 201 } 202 } 203 204 public void setShortcut(boolean showShortcut, char shortcutKey) { 205 final int newVisibility = (showShortcut && mItemData.shouldShowShortcut()) 206 ? VISIBLE : GONE; 207 208 if (newVisibility == VISIBLE) { 209 mShortcutView.setText(mItemData.getShortcutLabel()); 210 } 211 212 if (mShortcutView.getVisibility() != newVisibility) { 213 mShortcutView.setVisibility(newVisibility); 214 } 215 } 216 217 public void setIcon(Drawable icon) { 218 final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon; 219 if (!showIcon && !mPreserveIconSpacing) { 220 return; 221 } 222 223 if (mIconView == null && icon == null && !mPreserveIconSpacing) { 224 return; 225 } 226 227 if (mIconView == null) { 228 insertIconView(); 229 } 230 231 if (icon != null || mPreserveIconSpacing) { 232 mIconView.setImageDrawable(showIcon ? icon : null); 233 234 if (mIconView.getVisibility() != VISIBLE) { 235 mIconView.setVisibility(VISIBLE); 236 } 237 } else { 238 mIconView.setVisibility(GONE); 239 } 240 } 241 242 @Override 243 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 244 if (mIconView != null && mPreserveIconSpacing) { 245 // Enforce minimum icon spacing 246 ViewGroup.LayoutParams lp = getLayoutParams(); 247 LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); 248 if (lp.height > 0 && iconLp.width <= 0) { 249 iconLp.width = lp.height; 250 } 251 } 252 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 253 } 254 255 private void insertIconView() { 256 LayoutInflater inflater = getInflater(); 257 mIconView = (ImageView) inflater.inflate(R.layout.abc_list_menu_item_icon, 258 this, false); 259 addView(mIconView, 0); 260 } 261 262 private void insertRadioButton() { 263 LayoutInflater inflater = getInflater(); 264 mRadioButton = 265 (RadioButton) inflater.inflate(R.layout.abc_list_menu_item_radio, 266 this, false); 267 addView(mRadioButton); 268 } 269 270 private void insertCheckBox() { 271 LayoutInflater inflater = getInflater(); 272 mCheckBox = 273 (CheckBox) inflater.inflate(R.layout.abc_list_menu_item_checkbox, 274 this, false); 275 addView(mCheckBox); 276 } 277 278 public boolean prefersCondensedTitle() { 279 return false; 280 } 281 282 public boolean showsIcon() { 283 return mForceShowIcon; 284 } 285 286 private LayoutInflater getInflater() { 287 if (mInflater == null) { 288 mInflater = LayoutInflater.from(getContext()); 289 } 290 return mInflater; 291 } 292} 293 294