diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/view/Menu.java | 7 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/menu/ListMenuItemView.java | 92 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/menu/MenuAdapter.java | 8 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/menu/MenuBuilder.java | 16 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/menu/SubMenuBuilder.java | 10 | ||||
| -rw-r--r-- | core/res/res/layout/popup_menu_item_layout.xml | 104 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 1 |
10 files changed, 167 insertions, 74 deletions
diff --git a/api/current.txt b/api/current.txt index c147254494dd..7ced6a05643b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -44968,6 +44968,7 @@ package android.view { method public abstract void removeGroup(int); method public abstract void removeItem(int); method public abstract void setGroupCheckable(int, boolean, boolean); + method public default void setGroupDividerEnabled(boolean); method public abstract void setGroupEnabled(int, boolean); method public abstract void setGroupVisible(int, boolean); method public abstract void setQwertyMode(boolean); diff --git a/api/system-current.txt b/api/system-current.txt index ef12bfb4be1a..8f98e856391b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -48575,6 +48575,7 @@ package android.view { method public abstract void removeGroup(int); method public abstract void removeItem(int); method public abstract void setGroupCheckable(int, boolean, boolean); + method public default void setGroupDividerEnabled(boolean); method public abstract void setGroupEnabled(int, boolean); method public abstract void setGroupVisible(int, boolean); method public abstract void setQwertyMode(boolean); diff --git a/api/test-current.txt b/api/test-current.txt index 7203cad1cf32..7aac902c3d36 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -45414,6 +45414,7 @@ package android.view { method public abstract void removeGroup(int); method public abstract void removeItem(int); method public abstract void setGroupCheckable(int, boolean, boolean); + method public default void setGroupDividerEnabled(boolean); method public abstract void setGroupEnabled(int, boolean); method public abstract void setGroupVisible(int, boolean); method public abstract void setQwertyMode(boolean); diff --git a/core/java/android/view/Menu.java b/core/java/android/view/Menu.java index a8ea4dc1b8a0..6d1f740ad1da 100644 --- a/core/java/android/view/Menu.java +++ b/core/java/android/view/Menu.java @@ -451,5 +451,10 @@ public interface Menu { * will use numeric shortcuts. */ public void setQwertyMode(boolean isQwerty); -} + /** + * Enable or disable the group dividers. + */ + default void setGroupDividerEnabled(boolean groupDividerEnabled) { + } +}
\ No newline at end of file diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java index 83a2838be07e..f76c7247aba9 100644 --- a/core/java/com/android/internal/view/menu/ListMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java @@ -16,14 +16,18 @@ package com.android.internal.view.menu; +import com.android.internal.R; + import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.AbsListView; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; @@ -34,25 +38,28 @@ import android.widget.TextView; /** * The item view for each item in the ListView-based MenuViews. */ -public class ListMenuItemView extends LinearLayout implements MenuView.ItemView { +public class ListMenuItemView extends LinearLayout + implements MenuView.ItemView, AbsListView.SelectionBoundsAdjuster { private static final String TAG = "ListMenuItemView"; - private MenuItemImpl mItemData; - + private MenuItemImpl mItemData; + private ImageView mIconView; private RadioButton mRadioButton; private TextView mTitleView; private CheckBox mCheckBox; private TextView mShortcutView; private ImageView mSubMenuArrowView; - + private ImageView mGroupDivider; + private Drawable mBackground; private int mTextAppearance; private Context mTextAppearanceContext; private boolean mPreserveIconSpacing; private Drawable mSubMenuArrow; - + private boolean mHasListDivider; + private int mMenuType; - + private LayoutInflater mInflater; private boolean mForceShowIcon; @@ -71,8 +78,14 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView com.android.internal.R.styleable.MenuView_preserveIconSpacing, false); mTextAppearanceContext = context; mSubMenuArrow = a.getDrawable(com.android.internal.R.styleable.MenuView_subMenuArrow); - + + final TypedArray b = context.getTheme() + .obtainStyledAttributes(null, new int[] { com.android.internal.R.attr.divider }, + com.android.internal.R.attr.dropDownListViewStyle, 0); + mHasListDivider = b.hasValue(0); + a.recycle(); + b.recycle(); } public ListMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) { @@ -86,20 +99,21 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView @Override protected void onFinishInflate() { super.onFinishInflate(); - + setBackgroundDrawable(mBackground); - + mTitleView = findViewById(com.android.internal.R.id.title); if (mTextAppearance != -1) { mTitleView.setTextAppearance(mTextAppearanceContext, mTextAppearance); } - + mShortcutView = findViewById(com.android.internal.R.id.shortcut); mSubMenuArrowView = findViewById(com.android.internal.R.id.submenuarrow); if (mSubMenuArrowView != null) { mSubMenuArrowView.setImageDrawable(mSubMenuArrow); } + mGroupDivider = findViewById(com.android.internal.R.id.group_divider); } public void initialize(MenuItemImpl itemData, int menuType) { @@ -124,13 +138,13 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView public void setTitle(CharSequence title) { if (title != null) { mTitleView.setText(title); - + if (mTitleView.getVisibility() != VISIBLE) mTitleView.setVisibility(VISIBLE); } else { if (mTitleView.getVisibility() != GONE) mTitleView.setVisibility(GONE); } } - + public MenuItemImpl getItemData() { return mItemData; } @@ -139,11 +153,11 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView if (!checkable && mRadioButton == null && mCheckBox == null) { return; } - + // Depending on whether its exclusive check or not, the checkbox or // radio button will be the one in use (and the other will be otherCompoundButton) final CompoundButton compoundButton; - final CompoundButton otherCompoundButton; + final CompoundButton otherCompoundButton; if (mItemData.isExclusiveCheckable()) { if (mRadioButton == null) { @@ -158,15 +172,15 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView compoundButton = mCheckBox; otherCompoundButton = mRadioButton; } - + if (checkable) { compoundButton.setChecked(mItemData.isChecked()); - + final int newVisibility = checkable ? VISIBLE : GONE; if (compoundButton.getVisibility() != newVisibility) { compoundButton.setVisibility(newVisibility); } - + // Make sure the other compound button isn't visible if (otherCompoundButton != null && otherCompoundButton.getVisibility() != GONE) { otherCompoundButton.setVisibility(GONE); @@ -176,10 +190,10 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView if (mRadioButton != null) mRadioButton.setVisibility(GONE); } } - + public void setChecked(boolean checked) { CompoundButton compoundButton; - + if (mItemData.isExclusiveCheckable()) { if (mRadioButton == null) { insertRadioButton(); @@ -191,7 +205,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView } compoundButton = mCheckBox; } - + compoundButton.setChecked(checked); } @@ -213,21 +227,21 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView mShortcutView.setVisibility(newVisibility); } } - + public void setIcon(Drawable icon) { final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon; if (!showIcon && !mPreserveIconSpacing) { return; } - + if (mIconView == null && icon == null && !mPreserveIconSpacing) { return; } - + if (mIconView == null) { insertIconView(); } - + if (icon != null || mPreserveIconSpacing) { mIconView.setImageDrawable(showIcon ? icon : null); @@ -238,7 +252,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView mIconView.setVisibility(GONE); } } - + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mIconView != null && mPreserveIconSpacing) { @@ -258,7 +272,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView this, false); addView(mIconView, 0); } - + private void insertRadioButton() { LayoutInflater inflater = getInflater(); mRadioButton = @@ -266,7 +280,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView this, false); addView(mRadioButton); } - + private void insertCheckBox() { LayoutInflater inflater = getInflater(); mCheckBox = @@ -282,7 +296,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView public boolean showsIcon() { return mForceShowIcon; } - + private LayoutInflater getInflater() { if (mInflater == null) { mInflater = LayoutInflater.from(mContext); @@ -298,4 +312,26 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView info.setCanOpenPopup(true); } } + + /** + * Enable or disable group dividers for this view. + */ + public void setGroupDividerEnabled(boolean groupDividerEnabled) { + // If mHasListDivider is true, disabling the groupDivider. + // Otherwise, checking enbling it according to groupDividerEnabled flag. + mGroupDivider.setVisibility(!mHasListDivider + && groupDividerEnabled ? View.VISIBLE : View.GONE); + } + + @Override + public void adjustListItemSelectionBounds(Rect rect) { + if (mGroupDivider.getVisibility() == View.VISIBLE) { + // groupDivider is a part of MenuItemListView. + // If ListMenuItem with divider enabled is hovered/clicked, divider also gets selected. + // Clipping the selector bounds from the top divider portion when divider is enabled, + // so that divider does not get selected on hover or click. + final LayoutParams lp = (LayoutParams) mGroupDivider.getLayoutParams(); + rect.top += mGroupDivider.getHeight() + lp.topMargin + lp.bottomMargin; + } + } } diff --git a/core/java/com/android/internal/view/menu/MenuAdapter.java b/core/java/com/android/internal/view/menu/MenuAdapter.java index 673cfd12d878..2834d39a4f98 100644 --- a/core/java/com/android/internal/view/menu/MenuAdapter.java +++ b/core/java/com/android/internal/view/menu/MenuAdapter.java @@ -81,6 +81,14 @@ public class MenuAdapter extends BaseAdapter { convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); } + final int currGroupId = getItem(position).getGroupId(); + final int prevGroupId = + position - 1 >= 0 ? getItem(position - 1).getGroupId() : currGroupId; + // Show a divider if adjacent items are in different groups. + ((ListMenuItemView) convertView) + .setGroupDividerEnabled(mAdapterMenu.isGroupDividerEnabled() + && (currGroupId != prevGroupId)); + MenuView.ItemView itemView = (MenuView.ItemView) convertView; if (mForceShowIcon) { ((ListMenuItemView) convertView).setForceShowIcon(true); diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index 7eb0f4dbddc7..b53459e072d4 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -156,7 +156,12 @@ public class MenuBuilder implements Menu { * Currently expanded menu item; must be collapsed when we clear. */ private MenuItemImpl mExpandedItem; - + + /** + * Whether group dividers are enabled. + */ + private boolean mGroupDividerEnabled = false; + /** * Called by menu to notify of close and selection changes. */ @@ -462,6 +467,15 @@ public class MenuBuilder implements Menu { return addSubMenu(group, id, categoryOrder, mResources.getString(title)); } + @Override + public void setGroupDividerEnabled(boolean groupDividerEnabled) { + mGroupDividerEnabled = groupDividerEnabled; + } + + public boolean isGroupDividerEnabled() { + return mGroupDividerEnabled; + } + public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { PackageManager pm = mContext.getPackageManager(); diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java index cf741bf5bb02..897440ebf893 100644 --- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java +++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java @@ -130,4 +130,14 @@ public class SubMenuBuilder extends MenuBuilder implements SubMenu { } return super.getActionViewStatesKey() + ":" + itemId; } + + @Override + public void setGroupDividerEnabled(boolean groupDividerEnabled) { + mParentMenu.setGroupDividerEnabled(groupDividerEnabled); + } + + @Override + public boolean isGroupDividerEnabled() { + return mParentMenu.isGroupDividerEnabled(); + } } diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml index 8b8c93afffbd..3eecb36f0ea6 100644 --- a/core/res/res/layout/popup_menu_item_layout.xml +++ b/core/res/res/layout/popup_menu_item_layout.xml @@ -16,56 +16,72 @@ <com.android.internal.view.menu.ListMenuItemView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="?attr/dropdownListPreferredItemHeight" + android:layout_height="wrap_content" android:minWidth="196dip" - android:paddingEnd="16dip"> - + android:orientation="vertical" > + + <ImageView + android:id="@+id/group_divider" + android:layout_width="match_parent" + android:layout_height="1dip" + android:layout_marginTop="4dip" + android:layout_marginBottom="4dip" + android:background="@drawable/list_divider_material" /> + <!-- Icon will be inserted here. --> - - <!-- The title and summary have some gap between them, and this 'group' should be centered vertically. --> - <RelativeLayout - android:layout_width="0dip" - android:layout_weight="1" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginStart="16dip" - android:duplicateParentState="true"> - - <TextView - android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_alignParentStart="true" - android:textAppearance="?attr/textAppearanceLargePopupMenu" - android:singleLine="true" - android:duplicateParentState="true" - android:ellipsize="marquee" - android:fadingEdge="horizontal" - android:textAlignment="viewStart" /> - <TextView - android:id="@+id/shortcut" - android:layout_width="wrap_content" + <!-- The title and summary have some gap between them, + and this 'group' should be centered vertically. --> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="?attr/dropdownListPreferredItemHeight" + android:paddingEnd="16dip" + android:duplicateParentState="true" > + + <LinearLayout + android:layout_width="0dip" + android:layout_weight="1" android:layout_height="wrap_content" - android:layout_below="@id/title" - android:layout_alignParentStart="true" - android:textAppearance="?attr/textAppearanceSmallPopupMenu" - android:singleLine="true" - android:duplicateParentState="true" - android:textAlignment="viewStart" /> + android:layout_gravity="center_vertical" + android:layout_marginStart="16dip" + android:duplicateParentState="true"> - </RelativeLayout> + <TextView + android:id="@+id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:textAppearance="?attr/textAppearanceLargePopupMenu" + android:singleLine="true" + android:duplicateParentState="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:textAlignment="viewStart" /> - <ImageView - android:id="@+id/submenuarrow" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:layout_marginStart="8dp" - android:scaleType="center" - android:visibility="gone" /> + <TextView + android:id="@+id/shortcut" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/title" + android:layout_alignParentStart="true" + android:textAppearance="?attr/textAppearanceSmallPopupMenu" + android:singleLine="true" + android:duplicateParentState="true" + android:textAlignment="viewStart" /> + + </LinearLayout> + + <ImageView + android:id="@+id/submenuarrow" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginStart="8dp" + android:scaleType="center" + android:visibility="gone" /> + </LinearLayout> <!-- Checkbox, and/or radio button will be inserted here. --> - + </com.android.internal.view.menu.ListMenuItemView> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index c80d2473625b..eb314399e822 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -74,6 +74,7 @@ <java-symbol type="id" name="fillInIntent" /> <java-symbol type="id" name="find" /> <java-symbol type="id" name="fullscreenArea" /> + <java-symbol type="id" name="group_divider" /> <java-symbol type="id" name="hard_keyboard_section" /> <java-symbol type="id" name="hard_keyboard_switch" /> <java-symbol type="id" name="headers" /> |