Add support for custom action views in ActionBar menus
Change-Id: Ic7850bc00fcfe95d805dd6a1b15cb5d413942475
diff --git a/api/current.xml b/api/current.xml
index a3a56b4..b560d98 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2176,6 +2176,17 @@
visibility="public"
>
</field>
+<field name="actionLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843580"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="actionModeBackground"
type="int"
transient="false"
@@ -2220,6 +2231,17 @@
visibility="public"
>
</field>
+<field name="actionViewClass"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843581"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="activityCloseEnterAnimation"
type="int"
transient="false"
@@ -193228,6 +193250,17 @@
deprecated="not deprecated"
visibility="public"
>
+<method name="getActionView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getAlphabeticShortcut"
return="char"
abstract="true"
@@ -193404,6 +193437,19 @@
visibility="public"
>
</method>
+<method name="setActionView"
+ return="android.view.MenuItem"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
<method name="setAlphabeticShortcut"
return="android.view.MenuItem"
abstract="true"
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index d0985d9..7d5dcd8 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -16,8 +16,7 @@
package android.view;
-import java.io.IOException;
-import java.lang.reflect.Method;
+import com.android.internal.view.menu.MenuItemImpl;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -29,7 +28,9 @@
import android.util.AttributeSet;
import android.util.Xml;
-import com.android.internal.view.menu.MenuItemImpl;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
/**
* This class is used to instantiate menu XML files into Menu objects.
@@ -52,6 +53,8 @@
private static final int NO_ID = 0;
+ private static final Class<?>[] ACTION_VIEW_CONSTRUCTOR_SIGNATURE = new Class[]{Context.class};
+
private Context mContext;
/**
@@ -249,6 +252,9 @@
* - -1: Safe sentinel for "no value".
*/
private int itemShowAsAction;
+
+ private int itemActionViewLayout;
+ private String itemActionViewClassName;
private String itemListenerMethodName;
@@ -325,6 +331,8 @@
itemEnabled = a.getBoolean(com.android.internal.R.styleable.MenuItem_enabled, groupEnabled);
itemShowAsAction = a.getInt(com.android.internal.R.styleable.MenuItem_showAsAction, -1);
itemListenerMethodName = a.getString(com.android.internal.R.styleable.MenuItem_onClick);
+ itemActionViewLayout = a.getResourceId(com.android.internal.R.styleable.MenuItem_actionLayout, 0);
+ itemActionViewClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionViewClass);
a.recycle();
@@ -368,6 +376,19 @@
impl.setExclusiveCheckable(true);
}
}
+
+ if (itemActionViewClassName != null) {
+ try {
+ final Class<?> clazz = Class.forName(itemActionViewClassName);
+ Constructor<?> c = clazz.getConstructor(ACTION_VIEW_CONSTRUCTOR_SIGNATURE);
+ item.setActionView((View) c.newInstance(mContext));
+ } catch (Exception e) {
+ throw new InflateException(e);
+ }
+ } else if (itemActionViewLayout > 0) {
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ item.setActionView(inflater.inflate(itemActionViewLayout, null));
+ }
}
public void addItem() {
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 2604cf9..8b9d659 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -405,6 +405,29 @@
* {@link #SHOW_AS_ACTION_NEVER}. SHOW_AS_ACTION_NEVER is the default.
*
* @see android.app.ActionBar
+ * @see #setActionView(View)
*/
public void setShowAsAction(int actionEnum);
+
+ /**
+ * Set an action view for this menu item. An action view will be displayed in place
+ * of an automatically generated menu item element in the UI when this item is shown
+ * as an action within a parent.
+ *
+ * @param view View to use for presenting this item to the user.
+ * @return This Item so additional setters can be called.
+ *
+ * @see #setShowAsAction(int)
+ */
+ public MenuItem setActionView(View view);
+
+ /**
+ * Returns the currently set action view for this menu item.
+ *
+ * @return This item's action view
+ *
+ * @see #setActionView(View)
+ * @see #setShowAsAction(int)
+ */
+ public View getActionView();
}
\ No newline at end of file
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index 035875a..d2851a9 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -19,9 +19,10 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.SubMenu;
-import android.view.ContextMenu.ContextMenuInfo;
+import android.view.View;
/**
* @hide
@@ -222,4 +223,12 @@
public void setShowAsAction(int show) {
// Do nothing. ActionMenuItems always show as action buttons.
}
+
+ public MenuItem setActionView(View actionView) {
+ throw new UnsupportedOperationException();
+ }
+
+ public View getActionView() {
+ return null;
+ }
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index c4b6214..20939ab 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -21,6 +21,7 @@
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
+import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
@@ -158,8 +159,13 @@
for (int i = 0; i < itemCount; i++) {
final MenuItemImpl itemData = itemsToShow.get(i);
- addItemView((ActionMenuItemView) itemData.getItemView(MenuBuilder.TYPE_ACTION_BUTTON,
- this));
+ final View actionView = itemData.getActionView();
+ if (actionView != null) {
+ addView(actionView);
+ } else {
+ addItemView((ActionMenuItemView) itemData.getItemView(
+ MenuBuilder.TYPE_ACTION_BUTTON, this));
+ }
}
if (reserveOverflow) {
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 07a2a94..42f9771 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -78,6 +78,8 @@
private int mShowAsAction = SHOW_AS_ACTION_NEVER;
+ private View mActionView;
+
/** Used for the icon resource ID if this item does not have an icon */
static final int NO_ICON = 0;
@@ -666,4 +668,13 @@
mShowAsAction = actionEnum;
mMenu.onItemActionRequestChanged(this);
}
+
+ public MenuItem setActionView(View view) {
+ mActionView = view;
+ return this;
+ }
+
+ public View getActionView() {
+ return mActionView;
+ }
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3bee089..9363db5 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3502,6 +3502,16 @@
<enum name="always" value="2" />
</attr>
+ <!-- An optional layout to be used as an action view.
+ See {@link android.view.MenuItem#setActionView(android.view.View)}
+ for more info. -->
+ <attr name="actionLayout" format="reference" />
+
+ <!-- The name of an optional View class to instantiate and use as an
+ action view. See {@link android.view.MenuItem#setActionView(android.view.View)}
+ for more info. -->
+ <attr name="actionViewClass" format="string" />
+
</declare-styleable>
<!-- **************************************************************** -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0b32362..86e5579 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1344,6 +1344,8 @@
<public type="attr" name="titleTextStyle" />
<public type="attr" name="subtitleTextStyle" />
<public type="attr" name="iconifiedByDefault" />
+ <public type="attr" name="actionLayout" />
+ <public type="attr" name="actionViewClass" />
<public type="anim" name="animator_fade_in" />
<public type="anim" name="animator_fade_out" />