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