summaryrefslogtreecommitdiffstats
path: root/core/java/android/view
diff options
context:
space:
mode:
authorAdam Powell <adamp@google.com>2010-04-20 10:01:14 -0700
committerAdam Powell <adamp@google.com>2010-05-13 01:27:59 -0700
commit33b974393b6fadcefc896ec4a0f9b66724f61e9f (patch)
tree5c90001e5931a2cf09e9900c58d6d815d3dfa46b /core/java/android/view
parent5d8636dbada23bd40c80dbf43702d538b2997ac4 (diff)
downloadframeworks_base-33b974393b6fadcefc896ec4a0f9b66724f61e9f.zip
frameworks_base-33b974393b6fadcefc896ec4a0f9b66724f61e9f.tar.gz
frameworks_base-33b974393b6fadcefc896ec4a0f9b66724f61e9f.tar.bz2
ActionBar added to framework, integrated with Activity and styles.
Added onClick attribute support to menus in MenuInflater. Change-Id: I739771b4f249d87a0d8b15969f3d526b099067a1
Diffstat (limited to 'core/java/android/view')
-rw-r--r--core/java/android/view/ActionBarView.java625
-rw-r--r--core/java/android/view/MenuInflater.java50
-rw-r--r--core/java/android/view/Window.java17
3 files changed, 689 insertions, 3 deletions
diff --git a/core/java/android/view/ActionBarView.java b/core/java/android/view/ActionBarView.java
new file mode 100644
index 0000000..941ef21
--- /dev/null
+++ b/core/java/android/view/ActionBarView.java
@@ -0,0 +1,625 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import java.util.ArrayList;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.ActionBar.Callback;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.SparseArray;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.R;
+import com.android.internal.view.menu.ActionMenu;
+import com.android.internal.view.menu.ActionMenuItem;
+
+/**
+ * @hide
+ */
+public class ActionBarView extends ViewGroup {
+ private static final String TAG = "ActionBarView";
+
+ // TODO: This must be defined in the default theme
+ private static final int CONTENT_HEIGHT_DIP = 50;
+ private static final int CONTENT_PADDING_DIP = 3;
+ private static final int CONTENT_SPACING_DIP = 6;
+ private static final int CONTENT_ACTION_SPACING_DIP = 12;
+
+ /**
+ * Display options applied by default
+ */
+ public static final int DISPLAY_DEFAULT = 0;
+
+ /**
+ * Display options that require re-layout as opposed to a simple invalidate
+ */
+ private static final int DISPLAY_RELAYOUT_MASK = ActionBar.DISPLAY_USE_LOGO;
+
+ private final int mContentHeight;
+
+ private int mNavigationMode;
+ private int mDisplayOptions;
+ private int mSpacing;
+ private int mActionSpacing;
+ private CharSequence mTitle;
+ private CharSequence mSubtitle;
+ private Drawable mIcon;
+ private Drawable mLogo;
+ private Drawable mDivider;
+
+ private ImageView mIconView;
+ private ImageView mLogoView;
+ private TextView mTitleView;
+ private TextView mSubtitleView;
+ private View mNavigationView;
+
+ private boolean mShowMenu;
+
+ private ActionMenuItem mLogoNavItem;
+ private ActionMenu mNavMenu;
+ private ActionMenu mActionMenu;
+ private ActionMenu mOptionsMenu;
+
+ private SparseArray<ActionMenu> mContextMenus;
+
+ private Callback mCallback;
+
+ private final ArrayList<ActionView> mActions = new ArrayList<ActionView>();
+ private final OnClickListener mActionClickHandler = new OnClickListener() {
+ public void onClick(View v) {
+ ActionView av = (ActionView) v;
+ ActionMenuItem item = (ActionMenuItem) av.menuItem;
+
+ if (!mCallback.onActionItemSelected(item)) {
+ item.invoke();
+ }
+ }
+ };
+
+ private OnClickListener mHomeClickListener = null;
+
+ public ActionBarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+ mContentHeight = (int) (CONTENT_HEIGHT_DIP * metrics.density + 0.5f);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar);
+
+ final int colorFilter = a.getColor(R.styleable.ActionBar_colorFilter, 0);
+
+ if (colorFilter != 0) {
+ final Drawable d = getBackground();
+ d.setDither(true);
+ d.setColorFilter(new PorterDuffColorFilter(colorFilter, PorterDuff.Mode.OVERLAY));
+ }
+
+ ApplicationInfo info = context.getApplicationInfo();
+ PackageManager pm = context.getPackageManager();
+ mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode, ActionBar.NAVIGATION_MODE_NORMAL);
+ mTitle = a.getText(R.styleable.ActionBar_title);
+ mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
+ mDisplayOptions = a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT);
+
+ mLogo = a.getDrawable(R.styleable.ActionBar_logo);
+ if (mLogo == null) {
+ mLogo = info.loadLogo(pm);
+ }
+ mIcon = a.getDrawable(R.styleable.ActionBar_icon);
+ if (mIcon == null) {
+ mIcon = info.loadIcon(pm);
+ }
+ mDivider = a.getDrawable(R.styleable.ActionBar_divider);
+
+ Drawable background = a.getDrawable(R.styleable.ActionBar_background);
+ if (background != null) {
+ setBackgroundDrawable(background);
+ }
+
+ final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
+ if (customNavId != 0) {
+ LayoutInflater inflater = LayoutInflater.from(context);
+ mNavigationView = (View) inflater.inflate(customNavId, null);
+ mNavigationMode = ActionBar.NAVIGATION_MODE_CUSTOM;
+ }
+
+ a.recycle();
+
+ // TODO: Set this in the theme
+ int padding = (int) (CONTENT_PADDING_DIP * metrics.density + 0.5f);
+ setPadding(padding, padding, padding, padding);
+
+ mSpacing = (int) (CONTENT_SPACING_DIP * metrics.density + 0.5f);
+ mActionSpacing = (int) (CONTENT_ACTION_SPACING_DIP * metrics.density + 0.5f);
+
+ if (mLogo != null || mIcon != null || mTitle != null) {
+ mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
+ mHomeClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ if (mCallback != null) {
+ mCallback.onActionItemSelected(mLogoNavItem);
+ }
+ }
+ };
+ }
+
+ mContextMenus = new SparseArray<ActionMenu>();
+ }
+
+ private boolean initOptionsMenu() {
+ final Context context = getContext();
+ if (!(context instanceof Activity)) {
+ return false;
+ }
+
+ final Activity activity = (Activity) context;
+ ActionMenu optionsMenu = new ActionMenu(context);
+ if (activity.onCreateOptionsMenu(optionsMenu)) {
+ mOptionsMenu = optionsMenu;
+ return true;
+ }
+
+ return false;
+ }
+
+ public void setCallback(Callback callback) {
+ final Context context = getContext();
+ mCallback = callback;
+
+ ActionMenu actionMenu = new ActionMenu(context);
+ if (callback.onCreateActionMenu(actionMenu)) {
+ mActionMenu = actionMenu;
+ performUpdateActionMenu();
+ }
+ }
+
+ public void setCustomNavigationView(View view) {
+ mNavigationView = view;
+ if (view != null) {
+ setNavigationMode(ActionBar.NAVIGATION_MODE_CUSTOM);
+ }
+ requestLayout();
+ }
+
+ public void setDividerDrawable(Drawable d) {
+ mDivider = d;
+ }
+
+ public CharSequence getTitle() {
+ return mTitle;
+ }
+
+ public void setTitle(CharSequence title) {
+ mTitle = title;
+ if (mTitleView != null) {
+ mTitleView.setText(title);
+ }
+ if (mLogoNavItem != null) {
+ mLogoNavItem.setTitle(title);
+ }
+ }
+
+ public CharSequence getSubtitle() {
+ return mSubtitle;
+ }
+
+ public void setSubtitle(CharSequence subtitle) {
+ mSubtitle = subtitle;
+ if (mSubtitleView != null) {
+ mSubtitleView.setText(subtitle);
+ }
+ }
+
+ public void setDisplayOptions(int options) {
+ final int flagsChanged = options & mDisplayOptions;
+ mDisplayOptions = options;
+ if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
+ requestLayout();
+ } else {
+ invalidate();
+ }
+ }
+
+ public void setNavigationMode(int mode) {
+ if (mode != mNavigationMode) {
+ mNavigationMode = mode;
+ requestLayout();
+ }
+ }
+
+ public View getCustomNavigationView() {
+ return mNavigationView;
+ }
+
+ public int getNavigationMode() {
+ return mNavigationMode;
+ }
+
+ public int getDisplayOptions() {
+ return mDisplayOptions;
+ }
+
+ private ActionView findActionViewForItem(MenuItem item) {
+ final ArrayList<ActionView> actions = mActions;
+ final int actionCount = actions.size();
+ for (int i = 0; i < actionCount; i++) {
+ ActionView av = actions.get(i);
+ if (av.menuItem.equals(item)) {
+ return av;
+ }
+ }
+ return null;
+ }
+
+ public void setContextMode(int mode) {
+ Callback callback = mCallback;
+ if (callback == null) {
+ throw new IllegalStateException(
+ "Attempted to set ActionBar context mode with no callback");
+ }
+
+ ActionMenu menu = mContextMenus.get(mode);
+ if (menu == null) {
+ // Initialize the new mode
+ menu = new ActionMenu(getContext());
+
+ if (!callback.onCreateContextMode(mode, menu)) {
+ throw new IllegalArgumentException(
+ "ActionBar callback does not know how to create context mode " + mode);
+ }
+ mContextMenus.put(mode, menu);
+ }
+
+ if (callback.onPrepareContextMode(mode, menu)) {
+ // TODO Set mode, animate, etc.
+ }
+ }
+
+ public void exitContextMode() {
+ // TODO Turn off context mode; go back to normal.
+ }
+
+ public void updateActionMenu() {
+ final ActionMenu menu = mActionMenu;
+ if (menu == null || mCallback == null || !mCallback.onUpdateActionMenu(menu)) {
+ return;
+ }
+ performUpdateActionMenu();
+ }
+
+ private void performUpdateActionMenu() {
+ final ActionMenu menu = mActionMenu;
+ if (menu == null) {
+ return;
+ }
+ final Context context = getContext();
+
+ int childCount = getChildCount();
+ int childIndex = 0;
+ while (childIndex < childCount) {
+ View v = getChildAt(childIndex);
+ if (v instanceof ActionView) {
+ detachViewFromParent(childIndex);
+ childCount--;
+ } else {
+ childIndex++;
+ }
+ }
+
+ ArrayList<ActionView> detachedViews = new ArrayList<ActionView>(mActions);
+ final int itemCount = menu.size();
+ for (int i = 0; i < itemCount; i++) {
+ final MenuItem item = menu.getItem(i);
+
+ boolean newView = false;
+ ActionView actionView = findActionViewForItem(item);
+ if (actionView == null) {
+ actionView = new ActionView(context);
+ newView = true;
+ }
+ actionView.actionId = item.getItemId();
+ actionView.menuItem = item;
+ actionView.actionLabel = item.getTitle();
+ actionView.setAdjustViewBounds(true);
+ actionView.setImageDrawable(item.getIcon());
+ actionView.setOnClickListener(mActionClickHandler);
+
+ LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT, LayoutParams.ITEM_TYPE_ACTION);
+ actionView.setLayoutParams(layoutParams);
+
+ if (newView) {
+ addView(actionView);
+ mActions.add(actionView);
+ } else {
+ attachViewToParent(actionView, -1, layoutParams);
+ detachedViews.remove(actionView);
+ actionView.invalidate();
+ }
+ }
+
+ final int detachedCount = detachedViews.size();
+ for (int i = 0; i < detachedCount; i++) {
+ removeDetachedView(detachedViews.get(i), false);
+ }
+
+ requestLayout();
+ }
+
+ public void addAction(int id, Drawable icon, CharSequence label, OnActionListener listener) {
+ ActionView actionView = new ActionView(getContext());
+ actionView.actionId = id;
+ actionView.actionLabel = label;
+ actionView.actionListener = listener;
+ actionView.setAdjustViewBounds(true);
+ actionView.setImageDrawable(icon);
+ actionView.setOnClickListener(mActionClickHandler);
+
+ actionView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT, LayoutParams.ITEM_TYPE_ACTION));
+
+ addView(actionView);
+ mActions.add(actionView);
+
+ requestLayout();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ if ((mDisplayOptions & ActionBar.DISPLAY_HIDE_HOME) == 0) {
+ if (mLogo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
+ mLogoView = new ImageView(getContext());
+ mLogoView.setAdjustViewBounds(true);
+ mLogoView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT, LayoutParams.ITEM_TYPE_ICON));
+ mLogoView.setImageDrawable(mLogo);
+ mLogoView.setClickable(true);
+ mLogoView.setOnClickListener(mHomeClickListener);
+ addView(mLogoView);
+ } else if (mIcon != null) {
+ mIconView = new ImageView(getContext());
+ mIconView.setAdjustViewBounds(true);
+ mIconView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT, LayoutParams.ITEM_TYPE_ICON));
+ mIconView.setImageDrawable(mIcon);
+ mIconView.setClickable(true);
+ mIconView.setOnClickListener(mHomeClickListener);
+ addView(mIconView);
+ }
+ }
+
+ switch (mNavigationMode) {
+ case ActionBar.NAVIGATION_MODE_NORMAL:
+ if (mLogoView == null) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ mTitleView = (TextView) inflater.inflate(R.layout.action_bar_title_item, null);
+ mTitleView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT, LayoutParams.ITEM_TYPE_TITLE));
+ if (mTitle != null) {
+ mTitleView.setText(mTitle);
+ }
+ mTitleView.setClickable(true);
+ mTitleView.setOnClickListener(mHomeClickListener);
+ addView(mTitleView);
+ }
+ break;
+
+ case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
+ throw new UnsupportedOperationException(
+ "Dropdown list navigation isn't supported yet!");
+
+ case ActionBar.NAVIGATION_MODE_TABS:
+ throw new UnsupportedOperationException(
+ "Tab navigation isn't supported yet!");
+
+ case ActionBar.NAVIGATION_MODE_CUSTOM:
+ if (mNavigationView != null) {
+ mNavigationView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT, LayoutParams.ITEM_TYPE_CUSTOM_NAV));
+ addView(mNavigationView);
+ }
+ break;
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ if (widthMode != MeasureSpec.EXACTLY) {
+ throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
+ "with android:layout_width=\"match_parent\" (or fill_parent)");
+ }
+
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ if (heightMode != MeasureSpec.AT_MOST) {
+ throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
+ "with android:layout_height=\"wrap_content\"");
+ }
+
+ int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
+
+ int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight();
+ int childSpecHeight = MeasureSpec.makeMeasureSpec(mContentHeight - getPaddingTop() -
+ getPaddingBottom(), MeasureSpec.AT_MOST);
+
+ if (mLogoView != null) {
+ availableWidth = measureChildView(mLogoView, availableWidth, childSpecHeight, mSpacing);
+ }
+ if (mIconView != null) {
+ availableWidth = measureChildView(mIconView, availableWidth, childSpecHeight, mSpacing);
+ }
+
+ final ArrayList<ActionView> actions = mActions;
+ final int actionCount = actions.size();
+ for (int i = 0; i < actionCount; i++) {
+ ActionView action = actions.get(i);
+ availableWidth = measureChildView(action, availableWidth,
+ childSpecHeight, mActionSpacing);
+ }
+
+ switch (mNavigationMode) {
+ case ActionBar.NAVIGATION_MODE_NORMAL:
+ if (mTitleView != null) {
+ availableWidth = measureChildView(mTitleView, availableWidth,
+ childSpecHeight, mSpacing);
+ }
+ break;
+ case ActionBar.NAVIGATION_MODE_CUSTOM:
+ if (mNavigationView != null) {
+ availableWidth = measureChildView(mNavigationView, availableWidth,
+ childSpecHeight, mSpacing);
+ }
+ break;
+ }
+
+ setMeasuredDimension(contentWidth, mContentHeight);
+ }
+
+ private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) {
+ measureChild(child,
+ MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
+ childSpecHeight);
+
+ availableWidth -= child.getMeasuredWidth();
+ availableWidth -= spacing;
+
+ return availableWidth;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ int x = getPaddingLeft();
+ final int y = getPaddingTop();
+ final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
+
+ if (mLogoView != null) {
+ x += positionChild(mLogoView, x, y, contentHeight) + mSpacing;
+ }
+ if (mIconView != null) {
+ x += positionChild(mIconView, x, y, contentHeight) + mSpacing;
+ }
+
+ switch (mNavigationMode) {
+ case ActionBar.NAVIGATION_MODE_NORMAL:
+ if (mTitleView != null) {
+ x += positionChild(mTitleView, x, y, contentHeight) + mSpacing;
+ }
+ break;
+
+ case ActionBar.NAVIGATION_MODE_CUSTOM:
+ if (mNavigationView != null) {
+ x += positionChild(mNavigationView, x, y, contentHeight) + mSpacing;
+ }
+ break;
+ }
+
+ x = r - l - getPaddingRight();
+
+ final int count = mActions.size();
+ for (int i = count - 1; i >= 0; i--) {
+ ActionView action = mActions.get(i);
+ x -= (positionChildInverse(action, x, y, contentHeight) + mActionSpacing);
+ }
+ }
+
+ private int positionChild(View child, int x, int y, int contentHeight) {
+ int childWidth = child.getMeasuredWidth();
+ int childHeight = child.getMeasuredHeight();
+ int childTop = y + (contentHeight - childHeight) / 2;
+
+ child.layout(x, childTop, x + childWidth, childTop + childHeight);
+
+ return childWidth;
+ }
+
+ private int positionChildInverse(View child, int x, int y, int contentHeight) {
+ int childWidth = child.getMeasuredWidth();
+ int childHeight = child.getMeasuredHeight();
+ int childTop = y + (contentHeight - childHeight) / 2;
+
+ child.layout(x - childWidth, childTop, x, childTop + childHeight);
+
+ return childWidth;
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new ViewGroup.LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p != null && p instanceof LayoutParams;
+ }
+
+ private static class LayoutParams extends ViewGroup.LayoutParams {
+ static final int ITEM_TYPE_UNKNOWN = -1;
+ static final int ITEM_TYPE_ICON = 0;
+ static final int ITEM_TYPE_TITLE = 1;
+ static final int ITEM_TYPE_CUSTOM_NAV = 2;
+ static final int ITEM_TYPE_ACTION = 3;
+ static final int ITEM_TYPE_MORE = 4;
+
+ int type = ITEM_TYPE_UNKNOWN;
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ }
+
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ public LayoutParams(int width, int height, int type) {
+ this(width, height);
+ this.type = type;
+ }
+
+
+ public LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+ }
+
+ public interface OnActionListener {
+ void onAction(int id);
+ }
+
+ private static class ActionView extends ImageView {
+ int actionId;
+ CharSequence actionLabel;
+ OnActionListener actionListener;
+ MenuItem menuItem;
+
+ public ActionView(Context context) {
+ super(context);
+ }
+ }
+}
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 46c805c..a37d83d 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -16,9 +16,8 @@
package android.view;
-import com.android.internal.view.menu.MenuItemImpl;
-
import java.io.IOException;
+import java.lang.reflect.Method;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -30,6 +29,8 @@ import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.Xml;
+import com.android.internal.view.menu.MenuItemImpl;
+
/**
* This class is used to instantiate menu XML files into Menu objects.
* <p>
@@ -166,6 +167,41 @@ public class MenuInflater {
}
}
+ private static class InflatedOnMenuItemClickListener
+ implements MenuItem.OnMenuItemClickListener {
+ private static final Class[] PARAM_TYPES = new Class[] { MenuItem.class };
+
+ private Context mContext;
+ private Method mMethod;
+
+ public InflatedOnMenuItemClickListener(Context context, String methodName) {
+ mContext = context;
+ Class c = context.getClass();
+ try {
+ mMethod = c.getMethod(methodName, PARAM_TYPES);
+ } catch (Exception e) {
+ InflateException ex = new InflateException(
+ "Couldn't resolve menu item onClick handler " + methodName +
+ " in class " + c.getName());
+ ex.initCause(e);
+ throw ex;
+ }
+ }
+
+ public boolean onMenuItemClick(MenuItem item) {
+ try {
+ if (mMethod.getReturnType() == Boolean.TYPE) {
+ return (Boolean) mMethod.invoke(mContext, item);
+ } else {
+ mMethod.invoke(mContext, item);
+ return true;
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
/**
* State for the current menu.
* <p>
@@ -205,6 +241,8 @@ public class MenuInflater {
private boolean itemVisible;
private boolean itemEnabled;
+ private String itemListenerMethodName;
+
private static final int defaultGroupId = NO_ID;
private static final int defaultItemId = NO_ID;
private static final int defaultItemCategory = 0;
@@ -276,6 +314,7 @@ public class MenuInflater {
itemChecked = a.getBoolean(com.android.internal.R.styleable.MenuItem_checked, defaultItemChecked);
itemVisible = a.getBoolean(com.android.internal.R.styleable.MenuItem_visible, groupVisible);
itemEnabled = a.getBoolean(com.android.internal.R.styleable.MenuItem_enabled, groupEnabled);
+ itemListenerMethodName = a.getString(com.android.internal.R.styleable.MenuItem_onClick);
a.recycle();
@@ -299,8 +338,13 @@ public class MenuInflater {
.setIcon(itemIconResId)
.setAlphabeticShortcut(itemAlphabeticShortcut)
.setNumericShortcut(itemNumericShortcut);
+
+ if (itemListenerMethodName != null) {
+ item.setOnMenuItemClickListener(
+ new InflatedOnMenuItemClickListener(mContext, itemListenerMethodName));
+ }
- if (itemCheckable >= 2) {
+ if (itemCheckable >= 2 && item instanceof MenuItemImpl) {
((MenuItemImpl) item).setExclusiveCheckable(true);
}
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 7dd5085..e1ff4e8 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -61,6 +61,13 @@ public abstract class Window {
@hide
*/
public static final int FEATURE_OPENGL = 8;
+ /**
+ * Flag for enabling the Action Bar.
+ * This is enabled by default for some devices. The Action Bar
+ * replaces the title bar and provides an alternate location
+ * for an on-screen menu button on some devices.
+ */
+ public static final int FEATURE_ACTION_BAR = 9;
/** Flag for setting the progress bar's visibility to VISIBLE */
public static final int PROGRESS_VISIBILITY_ON = -1;
/** Flag for setting the progress bar's visibility to GONE */
@@ -981,6 +988,16 @@ public abstract class Window {
{
return mFeatures;
}
+
+ /**
+ * Query for the availability of a certain feature.
+ *
+ * @param feature The feature ID to check
+ * @return true if the feature is enabled, false otherwise.
+ */
+ public boolean hasFeature(int feature) {
+ return (getFeatures() & (1 << feature)) != 0;
+ }
/**
* Return the feature bits that are being implemented by this Window.