diff --git a/api/current.txt b/api/current.txt
index b017f9d2f5b94..b58947d36c0b3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -42593,6 +42593,7 @@ package android.view {
method public abstract android.view.ActionProvider getActionProvider();
method public abstract android.view.View getActionView();
method public abstract char getAlphabeticShortcut();
+ method public default java.lang.CharSequence getContentDescription();
method public abstract int getGroupId();
method public abstract android.graphics.drawable.Drawable getIcon();
method public abstract android.content.Intent getIntent();
@@ -42603,6 +42604,7 @@ package android.view {
method public abstract android.view.SubMenu getSubMenu();
method public abstract java.lang.CharSequence getTitle();
method public abstract java.lang.CharSequence getTitleCondensed();
+ method public default java.lang.CharSequence getTooltip();
method public abstract boolean hasSubMenu();
method public abstract boolean isActionViewExpanded();
method public abstract boolean isCheckable();
@@ -42615,6 +42617,7 @@ package android.view {
method public abstract android.view.MenuItem setAlphabeticShortcut(char);
method public abstract android.view.MenuItem setCheckable(boolean);
method public abstract android.view.MenuItem setChecked(boolean);
+ method public default android.view.MenuItem setContentDescription(java.lang.CharSequence);
method public abstract android.view.MenuItem setEnabled(boolean);
method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
method public abstract android.view.MenuItem setIcon(int);
@@ -42628,6 +42631,7 @@ package android.view {
method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
method public abstract android.view.MenuItem setTitle(int);
method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+ method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
method public abstract android.view.MenuItem setVisible(boolean);
field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
diff --git a/api/system-current.txt b/api/system-current.txt
index a5534deebd93e..7a0f24c3c9f92 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -45803,6 +45803,7 @@ package android.view {
method public abstract android.view.ActionProvider getActionProvider();
method public abstract android.view.View getActionView();
method public abstract char getAlphabeticShortcut();
+ method public default java.lang.CharSequence getContentDescription();
method public abstract int getGroupId();
method public abstract android.graphics.drawable.Drawable getIcon();
method public abstract android.content.Intent getIntent();
@@ -45813,6 +45814,7 @@ package android.view {
method public abstract android.view.SubMenu getSubMenu();
method public abstract java.lang.CharSequence getTitle();
method public abstract java.lang.CharSequence getTitleCondensed();
+ method public default java.lang.CharSequence getTooltip();
method public abstract boolean hasSubMenu();
method public abstract boolean isActionViewExpanded();
method public abstract boolean isCheckable();
@@ -45825,6 +45827,7 @@ package android.view {
method public abstract android.view.MenuItem setAlphabeticShortcut(char);
method public abstract android.view.MenuItem setCheckable(boolean);
method public abstract android.view.MenuItem setChecked(boolean);
+ method public default android.view.MenuItem setContentDescription(java.lang.CharSequence);
method public abstract android.view.MenuItem setEnabled(boolean);
method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
method public abstract android.view.MenuItem setIcon(int);
@@ -45838,6 +45841,7 @@ package android.view {
method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
method public abstract android.view.MenuItem setTitle(int);
method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+ method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
method public abstract android.view.MenuItem setVisible(boolean);
field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
diff --git a/api/test-current.txt b/api/test-current.txt
index 5db134a289646..4118053af2f7b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -42880,6 +42880,7 @@ package android.view {
method public abstract android.view.ActionProvider getActionProvider();
method public abstract android.view.View getActionView();
method public abstract char getAlphabeticShortcut();
+ method public default java.lang.CharSequence getContentDescription();
method public abstract int getGroupId();
method public abstract android.graphics.drawable.Drawable getIcon();
method public abstract android.content.Intent getIntent();
@@ -42890,6 +42891,7 @@ package android.view {
method public abstract android.view.SubMenu getSubMenu();
method public abstract java.lang.CharSequence getTitle();
method public abstract java.lang.CharSequence getTitleCondensed();
+ method public default java.lang.CharSequence getTooltip();
method public abstract boolean hasSubMenu();
method public abstract boolean isActionViewExpanded();
method public abstract boolean isCheckable();
@@ -42902,6 +42904,7 @@ package android.view {
method public abstract android.view.MenuItem setAlphabeticShortcut(char);
method public abstract android.view.MenuItem setCheckable(boolean);
method public abstract android.view.MenuItem setChecked(boolean);
+ method public default android.view.MenuItem setContentDescription(java.lang.CharSequence);
method public abstract android.view.MenuItem setEnabled(boolean);
method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
method public abstract android.view.MenuItem setIcon(int);
@@ -42915,6 +42918,7 @@ package android.view {
method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
method public abstract android.view.MenuItem setTitle(int);
method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+ method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
method public abstract android.view.MenuItem setVisible(boolean);
field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 73ea9ee31bce2..f3f3d40213ec3 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -334,6 +334,9 @@ public class MenuInflater {
private ActionProvider itemActionProvider;
+ private CharSequence itemContentDescription;
+ private CharSequence itemTooltip;
+
private static final int defaultGroupId = NO_ID;
private static final int defaultItemId = NO_ID;
private static final int defaultItemCategory = 0;
@@ -424,6 +427,10 @@ public class MenuInflater {
itemActionProvider = null;
}
+ itemContentDescription =
+ a.getText(com.android.internal.R.styleable.MenuItem_contentDescription);
+ itemTooltip = a.getText(com.android.internal.R.styleable.MenuItem_tooltip);
+
a.recycle();
itemAdded = false;
@@ -486,6 +493,9 @@ public class MenuInflater {
if (itemActionProvider != null) {
item.setActionProvider(itemActionProvider);
}
+
+ item.setContentDescription(itemContentDescription);
+ item.setTooltip(itemTooltip);
}
public MenuItem addItem() {
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 9e8b97eade6b1..5ced76592756b 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -599,4 +599,40 @@ public interface MenuItem {
* @return This menu item instance for call chaining
*/
public MenuItem setOnActionExpandListener(OnActionExpandListener listener);
+
+ /**
+ * Change the content description associated with this menu item.
+ *
+ * @param contentDescription The new content description.
+ */
+ default MenuItem setContentDescription(CharSequence contentDescription) {
+ return this;
+ }
+
+ /**
+ * Retrieve the content description associated with this menu item.
+ *
+ * @return The content description.
+ */
+ default CharSequence getContentDescription() {
+ return null;
+ }
+
+ /**
+ * Change the tooltip text associated with this menu item.
+ *
+ * @param tooltip The new tooltip text.
+ */
+ default MenuItem setTooltip(CharSequence tooltip) {
+ return this;
+ }
+
+ /**
+ * Retrieve the tooltip text associated with this menu item.
+ *
+ * @return The tooltip text.
+ */
+ default CharSequence getTooltip() {
+ return null;
+ }
}
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 83fc3623cf206..fc6448ad7eac7 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -249,6 +249,19 @@ public final class WindowManagerGlobal {
return views;
}
+ public View getWindowView(IBinder windowToken) {
+ synchronized (mLock) {
+ final int numViews = mViews.size();
+ for (int i = 0; i < numViews; ++i) {
+ final View view = mViews.get(i);
+ if (view.getWindowToken() == windowToken) {
+ return view;
+ }
+ }
+ }
+ return null;
+ }
+
public View getRootView(String name) {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
diff --git a/core/java/com/android/internal/view/TooltipPopup.java b/core/java/com/android/internal/view/TooltipPopup.java
index c5f6356e92b17..ebbbdbb0d6a6d 100644
--- a/core/java/com/android/internal/view/TooltipPopup.java
+++ b/core/java/com/android/internal/view/TooltipPopup.java
@@ -19,13 +19,17 @@ package com.android.internal.view;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.util.Slog;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.widget.TextView;
public class TooltipPopup {
+ private static final String TAG = "TooltipPopup";
+
private final Context mContext;
private final View mContentView;
@@ -34,6 +38,7 @@ public class TooltipPopup {
private final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
private final Rect mTmpDisplayFrame = new Rect();
private final int[] mTmpAnchorPos = new int[2];
+ private final int[] mTmpAppPos = new int[2];
public TooltipPopup(Context context) {
mContext = context;
@@ -124,8 +129,21 @@ public class TooltipPopup {
fromTouch ? com.android.internal.R.dimen.tooltip_y_offset_touch
: com.android.internal.R.dimen.tooltip_y_offset_non_touch);
- anchorView.getWindowVisibleDisplayFrame(mTmpDisplayFrame);
- anchorView.getLocationInWindow(mTmpAnchorPos);
+ // Find the main app window. The popup window will be positioned relative to it.
+ final View appView = WindowManagerGlobal.getInstance().getWindowView(
+ anchorView.getApplicationWindowToken());
+ if (appView == null) {
+ Slog.e(TAG, "Cannot find app view");
+ return;
+ }
+ appView.getWindowVisibleDisplayFrame(mTmpDisplayFrame);
+ appView.getLocationOnScreen(mTmpAppPos);
+
+ anchorView.getLocationOnScreen(mTmpAnchorPos);
+ mTmpAnchorPos[0] -= mTmpAppPos[0];
+ mTmpAnchorPos[1] -= mTmpAppPos[1];
+ // mTmpAnchorPos is now relative to the main app window.
+
outParams.x = mTmpAnchorPos[0] + offsetX - mTmpDisplayFrame.width() / 2;
final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index ed676bb703e9d..c8697ddba0296 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -39,23 +39,26 @@ public class ActionMenuItem implements MenuItem {
private Intent mIntent;
private char mShortcutNumericChar;
private char mShortcutAlphabeticChar;
-
+
private Drawable mIconDrawable;
private int mIconResId = NO_ICON;
-
+
private Context mContext;
-
+
private MenuItem.OnMenuItemClickListener mClickListener;
-
+
+ private CharSequence mContentDescription;
+ private CharSequence mTooltip;
+
private static final int NO_ICON = 0;
-
+
private int mFlags = ENABLED;
private static final int CHECKABLE = 0x00000001;
private static final int CHECKED = 0x00000002;
private static final int EXCLUSIVE = 0x00000004;
private static final int HIDDEN = 0x00000008;
private static final int ENABLED = 0x00000010;
-
+
public ActionMenuItem(Context context, int group, int id, int categoryOrder, int ordering,
CharSequence title) {
mContext = context;
@@ -65,7 +68,7 @@ public class ActionMenuItem implements MenuItem {
mOrdering = ordering;
mTitle = title;
}
-
+
public char getAlphabeticShortcut() {
return mShortcutAlphabeticChar;
}
@@ -274,4 +277,26 @@ public class ActionMenuItem implements MenuItem {
// No need to save the listener; ActionMenuItem does not support collapsing items.
return this;
}
+
+ @Override
+ public MenuItem setContentDescription(CharSequence contentDescription) {
+ mContentDescription = contentDescription;
+ return this;
+ }
+
+ @Override
+ public CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ @Override
+ public MenuItem setTooltip(CharSequence tooltip) {
+ mTooltip = tooltip;
+ return this;
+ }
+
+ @Override
+ public CharSequence getTooltip() {
+ return mTooltip;
+ }
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index af4f77786a5db..4ee59931d8315 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -119,7 +119,7 @@ public class ActionMenuItemView extends TextView
mItemData = itemData;
setIcon(itemData.getIcon());
- setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon
+ setTitle(itemData.getTitleForItemView(this)); // Title is only displayed if there is no icon
setId(itemData.getItemId());
setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
@@ -184,8 +184,22 @@ public class ActionMenuItemView extends TextView
setText(visible ? mTitle : null);
- // Show the tooltip for items that do not already show text.
- setTooltip(visible ? null : mTitle);
+ final CharSequence contentDescription = mItemData.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ // Use the uncondensed title for content description, but only if the title is not
+ // shown already.
+ setContentDescription(visible ? null : mItemData.getTitle());
+ } else {
+ setContentDescription(contentDescription);
+ }
+
+ final CharSequence tooltip = mItemData.getTooltip();
+ if (TextUtils.isEmpty(tooltip)) {
+ // Use the uncondensed title for tooltip, but only if the title is not shown already.
+ setTooltip(visible ? null : mItemData.getTitle());
+ } else {
+ setTooltip(tooltip);
+ }
}
public void setIcon(Drawable icon) {
@@ -221,7 +235,6 @@ public class ActionMenuItemView extends TextView
public void setTitle(CharSequence title) {
mTitle = title;
- setContentDescription(mTitle);
updateTextButtonVisibility();
}
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index 0e0c9b0cf244b..f9ebdbc4f0bb5 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.SoundEffectConstants;
@@ -31,7 +32,7 @@ import android.widget.TextView;
import android.text.Layout;
/**
- * The item view for each item in the {@link IconMenuView}.
+ * The item view for each item in the {@link IconMenuView}.
*/
public final class IconMenuItemView extends TextView implements MenuView.ItemView {
@@ -104,13 +105,23 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie
setTitle(title);
setIcon(icon);
+
+ if (mItemData != null) {
+ final CharSequence contentDescription = mItemData.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ setContentDescription(title);
+ } else {
+ setContentDescription(contentDescription);
+ }
+ setTooltip(mItemData.getTooltip());
+ }
}
-
+
public void initialize(MenuItemImpl itemData, int menuType) {
mItemData = itemData;
initialize(itemData.getTitleForItemView(this), itemData.getIcon());
-
+
setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
setEnabled(itemData.isEnabled());
}
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 25263932bb756..7c9f70902d05c 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -107,13 +107,15 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView
mMenuType = menuType;
setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
-
+
setTitle(itemData.getTitleForItemView(this));
setCheckable(itemData.isCheckable());
setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut());
setIcon(itemData.getIcon());
setEnabled(itemData.isEnabled());
setSubMenuArrowVisible(itemData.hasSubMenu());
+ setContentDescription(itemData.getContentDescription());
+ setTooltip(itemData.getTooltip());
}
public void setForceShowIcon(boolean forceShow) {
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 624c9e24e9451..cad0276165825 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -90,16 +90,19 @@ public final class MenuItemImpl implements MenuItem {
/**
* Current use case is for context menu: Extra information linked to the
* View that added this item to the context menu.
- */
+ */
private ContextMenuInfo mMenuInfo;
-
+
+ private CharSequence mContentDescription;
+ private CharSequence mTooltip;
+
private static String sLanguage;
private static String sPrependShortcutLabel;
private static String sEnterShortcutLabel;
private static String sDeleteShortcutLabel;
private static String sSpaceShortcutLabel;
-
-
+
+
/**
* Instantiates this menu item.
*
@@ -670,4 +673,32 @@ public final class MenuItemImpl implements MenuItem {
public boolean isActionViewExpanded() {
return mIsActionViewExpanded;
}
+
+ @Override
+ public MenuItem setContentDescription(CharSequence contentDescription) {
+ mContentDescription = contentDescription;
+
+ mMenu.onItemsChanged(false);
+
+ return this;
+ }
+
+ @Override
+ public CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ @Override
+ public MenuItem setTooltip(CharSequence tooltip) {
+ mTooltip = tooltip;
+
+ mMenu.onItemsChanged(false);
+
+ return this;
+ }
+
+ @Override
+ public CharSequence getTooltip() {
+ return mTooltip;
+ }
}
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 66042086e9257..04e09a85d1bfb 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1585,7 +1585,13 @@ public final class FloatingToolbar {
}
if (menuItem != null) {
menuButton.setText(menuItem.getTitle());
- menuButton.setContentDescription(menuItem.getTitle());
+ final CharSequence contentDescription = menuItem.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ menuButton.setContentDescription(menuItem.getTitle());
+ } else {
+ menuButton.setContentDescription(contentDescription);
+ }
+ menuButton.setTooltip(menuItem.getTooltip());
menuButton.setMinimumWidth(minimumWidth);
}
return menuButton;
@@ -1629,19 +1635,31 @@ public final class FloatingToolbar {
* Creates and returns a menu button for the specified menu item.
*/
private static View createMenuItemButton(Context context, MenuItem menuItem) {
+ final View menuItemButton;
if (isIconOnlyMenuItem(menuItem)) {
- View imageMenuItemButton = LayoutInflater.from(context)
+ menuItemButton = LayoutInflater.from(context)
.inflate(R.layout.floating_popup_menu_image_button, null);
- ((ImageButton) imageMenuItemButton
+ ((ImageButton) menuItemButton
.findViewById(R.id.floating_toolbar_menu_item_image_button))
.setImageDrawable(menuItem.getIcon());
- return imageMenuItemButton;
+ final CharSequence tooltip = menuItem.getTooltip();
+ if (TextUtils.isEmpty(tooltip)) {
+ menuItemButton.setTooltip(menuItem.getTitle());
+ } else {
+ menuItemButton.setTooltip(tooltip);
+ }
+ } else {
+ menuItemButton = LayoutInflater.from(context)
+ .inflate(R.layout.floating_popup_menu_button, null);
+ ((Button) menuItemButton).setText(menuItem.getTitle());
+ menuItemButton.setTooltip(menuItem.getTooltip());
+ }
+ final CharSequence contentDescription = menuItem.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ menuItemButton.setContentDescription(menuItem.getTitle());
+ } else {
+ menuItemButton.setContentDescription(contentDescription);
}
-
- Button menuItemButton = (Button) LayoutInflater.from(context)
- .inflate(R.layout.floating_popup_menu_button, null);
- menuItemButton.setText(menuItem.getTitle());
- menuItemButton.setContentDescription(menuItem.getTitle());
return menuItemButton;
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 05658b018861a..37b3ffc480168 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7009,6 +7009,12 @@
for more info. -->
+
+
+
+
+
+
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 0f756b94a3212..ce7ab1626aa0c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1290,6 +1290,7 @@ please see styles_device_defaults.xml.
@@ -994,6 +995,7 @@ please see styles_device_defaults.xml.
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index a1e12d281c951..709200eabff2d 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -944,6 +944,7 @@ please see styles_device_defaults.xml.
- @drawable/ic_menu_moreoverflow_material
- ?attr/actionBarItemBackground
- @string/action_menu_overflow_description
+ - @string/action_menu_overflow_description
- @dimen/action_button_min_width_overflow_material
- @dimen/action_button_min_height_material
- @dimen/action_bar_overflow_padding_start_material