summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Adam Powell <adamp@google.com> 2010-06-23 20:24:52 -0700
committer Adam Powell <adamp@google.com> 2010-06-29 14:04:58 -0700
commit89e0645b4157961e8c465eb9c819f965fdb453d8 (patch)
treeeb174c070624026930067c8472f5425cfc4034ab
parent6443de56f3bb9609698b41fc5de04559de039f63 (diff)
Added context modes to ActionBar API.
Change-Id: I7c3e782cbf01be7bc671b377fb4d706040888833
-rw-r--r--api/current.xml232
-rw-r--r--core/java/android/app/ActionBar.java164
-rw-r--r--core/java/android/app/Activity.java18
-rw-r--r--core/java/android/view/MenuInflater.java8
-rw-r--r--core/java/android/view/MenuItem.java24
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java214
-rw-r--r--core/java/com/android/internal/app/SplitActionBar.java105
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuItem.java4
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuView.java2
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java16
-rw-r--r--core/java/com/android/internal/widget/ActionBarContextView.java272
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java (renamed from core/java/android/view/ActionBarView.java)46
-rw-r--r--core/res/res/drawable/action_bar_context_background.xml23
-rw-r--r--core/res/res/layout/screen_action_bar.xml22
-rw-r--r--core/res/res/layout/screen_xlarge_action_bar.xml45
-rwxr-xr-xcore/res/res/values/attrs.xml2
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/themes.xml2
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java10
19 files changed, 928 insertions, 283 deletions
diff --git a/api/current.xml b/api/current.xml
index 0f774f2822be..72630eb14deb 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2088,6 +2088,28 @@
visibility="public"
>
</field>
+<field name="actionBarCloseContextDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843550"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionBarContextBackground"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843549"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="actionButtonPadding"
type="int"
transient="false"
@@ -19435,6 +19457,17 @@
visibility="public"
>
</constructor>
+<method name="finishContextMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getCustomNavigationView"
return="android.view.View"
abstract="true"
@@ -19503,19 +19536,6 @@
<parameter name="d" type="android.graphics.drawable.Drawable">
</parameter>
</method>
-<method name="setCallback"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.app.ActionBar.Callback">
-</parameter>
-</method>
<method name="setCustomNavigationMode"
return="void"
abstract="true"
@@ -19569,6 +19589,8 @@
>
<parameter name="adapter" type="android.widget.SpinnerAdapter">
</parameter>
+<parameter name="callback" type="android.app.ActionBar.NavigationCallback">
+</parameter>
</method>
<method name="setStandardNavigationMode"
return="void"
@@ -19598,6 +19620,19 @@
<parameter name="title" type="java.lang.CharSequence">
</parameter>
</method>
+<method name="startContextMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.app.ActionBar.ContextModeCallback">
+</parameter>
+</method>
<field name="DISPLAY_HIDE_HOME"
type="int"
transient="false"
@@ -19665,15 +19700,24 @@
>
</field>
</class>
-<interface name="ActionBar.Callback"
+<class name="ActionBar.ContextMode"
+ extends="java.lang.Object"
abstract="true"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
-<method name="onContextItemClicked"
- return="boolean"
+<constructor name="ActionBar.ContextMode"
+ type="android.app.ActionBar.ContextMode"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="finish"
+ return="void"
abstract="true"
native="false"
synchronized="false"
@@ -19682,13 +19726,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="modeId" type="int">
-</parameter>
-<parameter name="item" type="android.view.MenuItem">
-</parameter>
</method>
-<method name="onCreateContextMode"
- return="boolean"
+<method name="getMenu"
+ return="android.view.Menu"
abstract="true"
native="false"
synchronized="false"
@@ -19697,13 +19737,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="modeId" type="int">
-</parameter>
-<parameter name="menu" type="android.view.Menu">
-</parameter>
</method>
-<method name="onNavigationItemSelected"
- return="boolean"
+<method name="invalidate"
+ return="void"
abstract="true"
native="false"
synchronized="false"
@@ -19712,13 +19748,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="itemPosition" type="int">
-</parameter>
-<parameter name="itemId" type="long">
-</parameter>
</method>
-<method name="onPrepareContextMode"
- return="boolean"
+<method name="setCustomView"
+ return="void"
abstract="true"
native="false"
synchronized="false"
@@ -19727,33 +19759,46 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="modeId" type="int">
-</parameter>
-<parameter name="menu" type="android.view.Menu">
+<parameter name="view" type="android.view.View">
</parameter>
</method>
-</interface>
-<class name="ActionBar.SimpleCallback"
- extends="java.lang.Object"
- abstract="false"
- static="true"
+<method name="setSubtitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
-<implements name="android.app.ActionBar.Callback">
-</implements>
-<constructor name="ActionBar.SimpleCallback"
- type="android.app.ActionBar.SimpleCallback"
+<parameter name="subtitle" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
-</constructor>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+</method>
+</class>
+<interface name="ActionBar.ContextModeCallback"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
<method name="onContextItemClicked"
return="boolean"
- abstract="false"
+ abstract="true"
native="false"
synchronized="false"
static="false"
@@ -19761,14 +19806,14 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="modeId" type="int">
+<parameter name="mode" type="android.app.ActionBar.ContextMode">
</parameter>
<parameter name="item" type="android.view.MenuItem">
</parameter>
</method>
<method name="onCreateContextMode"
return="boolean"
- abstract="false"
+ abstract="true"
native="false"
synchronized="false"
static="false"
@@ -19776,14 +19821,14 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="modeId" type="int">
+<parameter name="mode" type="android.app.ActionBar.ContextMode">
</parameter>
<parameter name="menu" type="android.view.Menu">
</parameter>
</method>
-<method name="onNavigationItemSelected"
- return="boolean"
- abstract="false"
+<method name="onDestroyContextMode"
+ return="void"
+ abstract="true"
native="false"
synchronized="false"
static="false"
@@ -19791,14 +19836,12 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="itemPosition" type="int">
-</parameter>
-<parameter name="itemId" type="long">
+<parameter name="mode" type="android.app.ActionBar.ContextMode">
</parameter>
</method>
<method name="onPrepareContextMode"
return="boolean"
- abstract="false"
+ abstract="true"
native="false"
synchronized="false"
static="false"
@@ -19806,12 +19849,35 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="modeId" type="int">
+<parameter name="mode" type="android.app.ActionBar.ContextMode">
</parameter>
<parameter name="menu" type="android.view.Menu">
</parameter>
</method>
-</class>
+</interface>
+<interface name="ActionBar.NavigationCallback"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onNavigationItemSelected"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="itemPosition" type="int">
+</parameter>
+<parameter name="itemId" type="long">
+</parameter>
+</method>
+</interface>
<class name="Activity"
extends="android.view.ContextThemeWrapper"
abstract="false"
@@ -180005,6 +180071,19 @@
<parameter name="alphaChar" type="char">
</parameter>
</method>
+<method name="setShowAsAction"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="actionEnum" type="int">
+</parameter>
+</method>
<method name="setTitle"
return="android.view.MenuItem"
abstract="true"
@@ -180057,6 +180136,39 @@
<parameter name="visible" type="boolean">
</parameter>
</method>
+<field name="SHOW_AS_ACTION_ALWAYS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOW_AS_ACTION_IF_ROOM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOW_AS_ACTION_NEVER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</interface>
<interface name="MenuItem.OnMenuItemClickListener"
abstract="true"
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 4387361da041..1775a0daa2eb 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -66,14 +66,7 @@ public abstract class ActionBar {
* navigation elements. This includes logo and icon.
*/
public static final int DISPLAY_HIDE_HOME = 0x2;
-
- /**
- * Set the callback that the ActionBar will use to handle events
- * and populate menus.
- * @param callback Callback to use
- */
- public abstract void setCallback(Callback callback);
-
+
/**
* Set the action bar into custom navigation mode, supplying a view
* for custom navigation.
@@ -95,8 +88,11 @@ public abstract class ActionBar {
* @param adapter An adapter that will provide views both to display
* the current navigation selection and populate views
* within the dropdown navigation menu.
+ * @param callback A NavigationCallback that will receive events when the user
+ * selects a navigation item.
*/
- public abstract void setDropdownNavigationMode(SpinnerAdapter adapter);
+ public abstract void setDropdownNavigationMode(SpinnerAdapter adapter,
+ NavigationCallback callback);
/**
* Set the action bar into standard navigation mode, supplying a title and subtitle.
@@ -198,48 +194,136 @@ public abstract class ActionBar {
*/
public abstract int getDisplayOptions();
+ public abstract void startContextMode(ContextModeCallback callback);
+ public abstract void finishContextMode();
+
/**
- * Callback interface for ActionBar events.
+ * Represents a contextual mode of the Action Bar. Context modes can be used for
+ * modal interactions with activity content and replace the normal Action Bar until finished.
+ * Examples of good contextual modes include selection modes, search, content editing, etc.
*/
- public interface Callback {
+ public static abstract class ContextMode {
/**
- * This method is called whenever a navigation item in your action bar
- * is selected.
- *
- * @param itemPosition Position of the item clicked.
- * @param itemId ID of the item clicked.
- * @return True if the event was handled, false otherwise.
+ * Set the title of the context mode. This method will have no visible effect if
+ * a custom view has been set.
+ *
+ * @param title Title string to set
+ *
+ * @see #setCustomView(View)
*/
- public boolean onNavigationItemSelected(int itemPosition, long itemId);
+ public abstract void setTitle(CharSequence title);
- /*
- * In progress
+ /**
+ * Set the subtitle of the context mode. This method will have no visible effect if
+ * a custom view has been set.
+ *
+ * @param subtitle Subtitle string to set
+ *
+ * @see #setCustomView(View)
*/
- public boolean onCreateContextMode(int modeId, Menu menu);
- public boolean onPrepareContextMode(int modeId, Menu menu);
- public boolean onContextItemClicked(int modeId, MenuItem item);
+ public abstract void setSubtitle(CharSequence subtitle);
+
+ /**
+ * Set a custom view for this context mode. The custom view will take the place of
+ * the title and subtitle. Useful for things like search boxes.
+ *
+ * @param view Custom view to use in place of the title/subtitle.
+ *
+ * @see #setTitle(CharSequence)
+ * @see #setSubtitle(CharSequence)
+ */
+ public abstract void setCustomView(View view);
+
+ /**
+ * Invalidate the context mode and refresh menu content. The context mode's
+ * {@link ContextModeCallback} will have its
+ * {@link ContextModeCallback#onPrepareContextMode(ContextMode, Menu)} method called.
+ * If it returns true the menu will be scanned for updated content and any relevant changes
+ * will be reflected to the user.
+ */
+ public abstract void invalidate();
+
+ /**
+ * Finish and close this context mode. The context mode's {@link ContextModeCallback} will
+ * have its {@link ContextModeCallback#onDestroyContextMode(ContextMode)} method called.
+ */
+ public abstract void finish();
+
+ /**
+ * Returns the menu of actions that this context mode presents.
+ * @return The context mode's menu.
+ */
+ public abstract Menu getMenu();
}
/**
- * Simple stub implementations of ActionBar.Callback methods.
- * Extend this if you only need a subset of Callback functionality.
+ * Callback interface for ActionBar context modes. Supplied to
+ * {@link ActionBar#startContextMode(ContextModeCallback)}, a ContextModeCallback
+ * configures and handles events raised by a user's interaction with a context mode.
+ *
+ * <p>A context mode's lifecycle is as follows:
+ * <ul>
+ * <li>{@link ContextModeCallback#onCreateContextMode(ContextMode, Menu)} once on initial
+ * creation</li>
+ * <li>{@link ContextModeCallback#onPrepareContextMode(ContextMode, Menu)} after creation
+ * and any time the {@link ContextMode} is invalidated</li>
+ * <li>{@link ContextModeCallback#onContextItemClicked(ContextMode, MenuItem)} any time a
+ * contextual action button is clicked</li>
+ * <li>{@link ContextModeCallback#onDestroyContextMode(ContextMode)} when the context mode
+ * is closed</li>
+ * </ul>
*/
- public static class SimpleCallback implements Callback {
- public boolean onCreateContextMode(int modeId, Menu menu) {
- return false;
- }
+ public interface ContextModeCallback {
+ /**
+ * Called when a context mode is first created. The menu supplied will be used to generate
+ * action buttons for the context mode.
+ *
+ * @param mode ContextMode being created
+ * @param menu Menu used to populate contextual action buttons
+ * @return true if the context mode should be created, false if entering this context mode
+ * should be aborted.
+ */
+ public boolean onCreateContextMode(ContextMode mode, Menu menu);
- public boolean onPrepareContextMode(int modeId, Menu menu) {
- return false;
- }
+ /**
+ * Called to refresh a context mode's action menu whenever it is invalidated.
+ *
+ * @param mode ContextMode being prepared
+ * @param menu Menu used to populate contextual action buttons
+ * @return true if the menu or context mode was updated, false otherwise.
+ */
+ public boolean onPrepareContextMode(ContextMode mode, Menu menu);
- public boolean onContextItemClicked(int modeId, MenuItem item) {
- return false;
- }
-
- public boolean onNavigationItemSelected(int itemPosition, long itemId) {
- return false;
- }
+ /**
+ * Called to report a user click on a contextual action button.
+ *
+ * @param mode The current ContextMode
+ * @param item The item that was clicked
+ * @return true if this callback handled the event, false if the standard MenuItem
+ * invocation should continue.
+ */
+ public boolean onContextItemClicked(ContextMode mode, MenuItem item);
+
+ /**
+ * Called when a context mode is about to be exited and destroyed.
+ *
+ * @param mode The current ContextMode being destroyed
+ */
+ public void onDestroyContextMode(ContextMode mode);
+ }
+
+ /**
+ * Callback interface for ActionBar navigation events.
+ */
+ public interface NavigationCallback {
+ /**
+ * This method is called whenever a navigation item in your action bar
+ * is selected.
+ *
+ * @param itemPosition Position of the item clicked.
+ * @param itemId ID of the item clicked.
+ * @return True if the event was handled, false otherwise.
+ */
+ public boolean onNavigationItemSelected(int itemPosition, long itemId);
}
-
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 91ff0a524d32..8825b8cc7587 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -52,7 +52,6 @@ import android.util.Config;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
-import android.view.ActionBarView;
import android.view.ContextMenu;
import android.view.ContextThemeWrapper;
import android.view.InflateException;
@@ -74,8 +73,9 @@ import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
import android.widget.LinearLayout;
-import com.android.internal.app.SplitActionBar;
+import com.android.internal.app.ActionBarImpl;
import com.android.internal.policy.PolicyManager;
+import com.android.internal.widget.ActionBarView;
/**
* An activity is a single, focused thing that the user can do. Almost all
@@ -1675,20 +1675,12 @@ public class Activity extends ContextThemeWrapper
* initializes the ActionBar with the view, and sets mActionBar.
*/
private void initActionBar() {
- if (!getWindow().hasFeature(Window.FEATURE_ACTION_BAR)) {
+ Window window = getWindow();
+ if (!window.hasFeature(Window.FEATURE_ACTION_BAR)) {
return;
}
- ActionBarView view = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
- if (view != null) {
- LinearLayout splitView =
- (LinearLayout) findViewById(com.android.internal.R.id.context_action_bar);
- if (splitView != null) {
- mActionBar = new SplitActionBar(view, splitView);
- }
- } else {
- Log.e(TAG, "Could not create action bar; view not found in window decor.");
- }
+ mActionBar = new ActionBarImpl(getWindow().getDecorView());
}
/**
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 3335e85436c8..4a966b5d77c0 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -242,12 +242,12 @@ public class MenuInflater {
private boolean itemEnabled;
/**
- * Sync to attrs.xml enum:
+ * Sync to attrs.xml enum, values in MenuItem:
* - 0: never
* - 1: ifRoom
* - 2: always
*/
- private int itemShowAsAction;
+ private int itemShowAsAction = MenuItem.SHOW_AS_ACTION_NEVER;
private String itemListenerMethodName;
@@ -346,7 +346,8 @@ public class MenuInflater {
.setTitleCondensed(itemTitleCondensed)
.setIcon(itemIconResId)
.setAlphabeticShortcut(itemAlphabeticShortcut)
- .setNumericShortcut(itemNumericShortcut);
+ .setNumericShortcut(itemNumericShortcut)
+ .setShowAsAction(itemShowAsAction);
if (itemListenerMethodName != null) {
item.setOnMenuItemClickListener(
@@ -358,7 +359,6 @@ public class MenuInflater {
if (itemCheckable >= 2) {
impl.setExclusiveCheckable(true);
}
- impl.setShowAsAction(itemShowAsAction);
}
}
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index fcebec5d8766..bfa349c7bf0b 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -31,6 +31,21 @@ import android.view.View.OnCreateContextMenuListener;
* For a feature set of specific menu types, see {@link Menu}.
*/
public interface MenuItem {
+ /*
+ * These should be kept in sync with attrs.xml enum constants for showAsAction
+ */
+ /** Never show this item as a button in an Action Bar. */
+ public static final int SHOW_AS_ACTION_NEVER = 0;
+ /** Show this item as a button in an Action Bar if the system decides there is room for it. */
+ public static final int SHOW_AS_ACTION_IF_ROOM = 1;
+ /**
+ * Always show this item as a button in an Action Bar.
+ * Use sparingly! If too many items are set to always show in the Action Bar it can
+ * crowd the Action Bar and degrade the user experience on devices with smaller screens.
+ * A good rule of thumb is to have no more than 2 items set to always show at a time.
+ */
+ public static final int SHOW_AS_ACTION_ALWAYS = 2;
+
/**
* Interface definition for a callback to be invoked when a menu item is
* clicked.
@@ -381,4 +396,13 @@ public interface MenuItem {
* menu item to the menu. This can be null.
*/
public ContextMenuInfo getMenuInfo();
+
+ /**
+ * Sets how this item should display in the presence of an Action Bar.
+ *
+ * @param actionEnum How the item should display. One of
+ *
+ * @see android.app.ActionBar
+ */
+ public void setShowAsAction(int actionEnum);
} \ No newline at end of file
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
new file mode 100644
index 000000000000..b36524e2d676
--- /dev/null
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -0,0 +1,214 @@
+/*
+ * 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 com.android.internal.app;
+
+import com.android.internal.view.menu.ActionMenu;
+import com.android.internal.view.menu.ActionMenuItem;
+import com.android.internal.widget.ActionBarContextView;
+import com.android.internal.widget.ActionBarView;
+
+import android.app.ActionBar;
+import android.graphics.drawable.Drawable;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.SpinnerAdapter;
+import android.widget.ViewAnimator;
+
+/**
+ * ActionBarImpl is the ActionBar implementation used
+ * by devices of all screen sizes. If it detects a compatible decor,
+ * it will split contextual modes across both the ActionBarView at
+ * the top of the screen and a horizontal LinearLayout at the bottom
+ * which is normally hidden.
+ */
+public class ActionBarImpl extends ActionBar {
+ private static final int NORMAL_VIEW = 0;
+ private static final int CONTEXT_VIEW = 1;
+
+ private ViewAnimator mAnimatorView;
+ private ActionBarView mActionView;
+ private ActionBarContextView mUpperContextView;
+ private LinearLayout mLowerContextView;
+
+ private ContextMode mContextMode;
+
+ private static final int CONTEXT_DISPLAY_NORMAL = 0;
+ private static final int CONTEXT_DISPLAY_SPLIT = 1;
+
+ private int mContextDisplayMode;
+
+ public ActionBarImpl(View decor) {
+ mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
+ mUpperContextView = (ActionBarContextView) decor.findViewById(
+ com.android.internal.R.id.action_context_bar);
+ mLowerContextView = (LinearLayout) decor.findViewById(
+ com.android.internal.R.id.lower_action_context_bar);
+ mAnimatorView = (ViewAnimator) decor.findViewById(
+ com.android.internal.R.id.action_bar_animator);
+
+ if (mActionView == null || mUpperContextView == null || mAnimatorView == null) {
+ throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
+ "with a compatible window decor layout");
+ }
+
+ mContextDisplayMode = mLowerContextView == null ?
+ CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
+ }
+
+ public void setCustomNavigationMode(View view) {
+ mActionView.setCustomNavigationView(view);
+ mActionView.setCallback(null);
+ }
+
+ public void setDropdownNavigationMode(SpinnerAdapter adapter, NavigationCallback callback) {
+ mActionView.setCallback(callback);
+ mActionView.setNavigationMode(NAVIGATION_MODE_DROPDOWN_LIST);
+ mActionView.setDropdownAdapter(adapter);
+ }
+
+ public void setStandardNavigationMode(CharSequence title) {
+ setStandardNavigationMode(title, null);
+ }
+
+ public void setStandardNavigationMode(CharSequence title, CharSequence subtitle) {
+ mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
+ mActionView.setTitle(title);
+ mActionView.setSubtitle(subtitle);
+ mActionView.setCallback(null);
+ }
+
+ public void setDisplayOptions(int options) {
+ mActionView.setDisplayOptions(options);
+ }
+
+ public void setDisplayOptions(int options, int mask) {
+ final int current = mActionView.getDisplayOptions();
+ mActionView.setDisplayOptions((options & mask) | (current & ~mask));
+ }
+
+ public void setBackgroundDrawable(Drawable d) {
+ mActionView.setBackgroundDrawable(d);
+ }
+
+ public View getCustomNavigationView() {
+ return mActionView.getCustomNavigationView();
+ }
+
+ public CharSequence getTitle() {
+ return mActionView.getTitle();
+ }
+
+ public CharSequence getSubtitle() {
+ return mActionView.getSubtitle();
+ }
+
+ public int getNavigationMode() {
+ return mActionView.getNavigationMode();
+ }
+
+ public int getDisplayOptions() {
+ return mActionView.getDisplayOptions();
+ }
+
+ @Override
+ public void startContextMode(ContextModeCallback callback) {
+ if (mContextMode != null) {
+ mContextMode.finish();
+ }
+ mContextMode = new ContextMode(callback);
+ if (callback.onCreateContextMode(mContextMode, mContextMode.getMenu())) {
+ mContextMode.invalidate();
+ mUpperContextView.initForMode(mContextMode);
+ mAnimatorView.setDisplayedChild(CONTEXT_VIEW);
+ if (mLowerContextView != null) {
+ // TODO animate this
+ mLowerContextView.setVisibility(View.VISIBLE);
+ }
+ }
+ }
+
+ @Override
+ public void finishContextMode() {
+ if (mContextMode != null) {
+ mContextMode.finish();
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public class ContextMode extends ActionBar.ContextMode {
+ private ContextModeCallback mCallback;
+ private ActionMenu mMenu;
+
+ public ContextMode(ContextModeCallback callback) {
+ mCallback = callback;
+ mMenu = new ActionMenu(mActionView.getContext());
+ }
+
+ @Override
+ public Menu getMenu() {
+ return mMenu;
+ }
+
+ @Override
+ public void finish() {
+ mCallback.onDestroyContextMode(this);
+ mUpperContextView.closeMode();
+ if (mLowerContextView != null) {
+ mLowerContextView.removeAllViews();
+ }
+ mAnimatorView.setDisplayedChild(NORMAL_VIEW);
+ if (mLowerContextView != null && mLowerContextView.getVisibility() != View.GONE) {
+ // TODO Animate this
+ mLowerContextView.setVisibility(View.GONE);
+ }
+ mContextMode = null;
+ }
+
+ @Override
+ public void invalidate() {
+ if (mCallback.onPrepareContextMode(this, mMenu)) {
+ // Refresh content in both context views
+ }
+ }
+
+ @Override
+ public void setCustomView(View view) {
+ mUpperContextView.setCustomView(view);
+ }
+
+ @Override
+ public void setSubtitle(CharSequence subtitle) {
+ mUpperContextView.setSubtitle(subtitle);
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ mUpperContextView.setTitle(title);
+ }
+
+ public void dispatchOnContextItemClicked(MenuItem item) {
+ ActionMenuItem actionItem = (ActionMenuItem) item;
+ if (!actionItem.invoke()) {
+ mCallback.onContextItemClicked(this, item);
+ }
+ }
+ }
+}
diff --git a/core/java/com/android/internal/app/SplitActionBar.java b/core/java/com/android/internal/app/SplitActionBar.java
deleted file mode 100644
index 05ae79395930..000000000000
--- a/core/java/com/android/internal/app/SplitActionBar.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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 com.android.internal.app;
-
-import android.app.ActionBar;
-import android.graphics.drawable.Drawable;
-import android.view.ActionBarView;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.SpinnerAdapter;
-
-/**
- * SplitActionBar is the ActionBar implementation used
- * by small-screen devices. It expects to split contextual
- * modes across both the ActionBarView at the top of the screen
- * and a horizontal LinearLayout at the bottom which is normally
- * hidden.
- */
-public class SplitActionBar extends ActionBar {
- private ActionBarView mActionView;
- private LinearLayout mContextView;
-
- public SplitActionBar(ActionBarView view, LinearLayout contextView) {
- mActionView = view;
- mContextView = contextView;
- }
-
- public void setCallback(Callback callback) {
- mActionView.setCallback(callback);
- }
-
- public void setCustomNavigationMode(View view) {
- mActionView.setCustomNavigationView(view);
- }
-
- public void setDropdownNavigationMode(SpinnerAdapter adapter) {
- mActionView.setNavigationMode(NAVIGATION_MODE_DROPDOWN_LIST);
- mActionView.setDropdownAdapter(adapter);
- }
-
- public void setStandardNavigationMode(CharSequence title) {
- setStandardNavigationMode(title, null);
- }
-
- public void setStandardNavigationMode(CharSequence title, CharSequence subtitle) {
- mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
- mActionView.setTitle(title);
- mActionView.setSubtitle(subtitle);
- }
-
- public void setTitle(CharSequence title) {
- mActionView.setTitle(title);
- }
-
- public void setSubtitle(CharSequence subtitle) {
- mActionView.setSubtitle(subtitle);
- }
-
- public void setDisplayOptions(int options) {
- mActionView.setDisplayOptions(options);
- }
-
- public void setDisplayOptions(int options, int mask) {
- final int current = mActionView.getDisplayOptions();
- mActionView.setDisplayOptions((options & mask) | (current & ~mask));
- }
-
- public void setBackgroundDrawable(Drawable d) {
- mActionView.setBackgroundDrawable(d);
- }
-
- public View getCustomNavigationView() {
- return mActionView.getCustomNavigationView();
- }
-
- public CharSequence getTitle() {
- return mActionView.getTitle();
- }
-
- public CharSequence getSubtitle() {
- return mActionView.getSubtitle();
- }
-
- public int getNavigationMode() {
- return mActionView.getNavigationMode();
- }
-
- public int getDisplayOptions() {
- return mActionView.getDisplayOptions();
- }
-}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index 47d5fb97737b..035875ac0bf4 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -218,4 +218,8 @@ public class ActionMenuItem implements MenuItem {
return false;
}
+
+ public void setShowAsAction(int show) {
+ // Do nothing. ActionMenuItems always show as action buttons.
+ }
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 97d27ac25da4..c3fe5dcba0c7 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -53,7 +53,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
final Resources res = getResources();
final int size = res.getDimensionPixelSize(com.android.internal.R.dimen.action_icon_size);
final int spaceAvailable = res.getDisplayMetrics().widthPixels / 2;
- final int itemSpace = size + mItemPadding;
+ final int itemSpace = size + mItemPadding;
mMaxItems = spaceAvailable / (itemSpace > 0 ? itemSpace : 1);
}
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index dc1e81f04b1d..5fe75be927fd 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -75,13 +75,7 @@ public final class MenuItemImpl implements MenuItem {
private static final int HIDDEN = 0x00000008;
private static final int ENABLED = 0x00000010;
private static final int IS_ACTION = 0x00000020;
-
- /*
- * These should be kept in sync with attrs.xml enum constants for showAsAction
- */
- private static final int SHOW_AS_ACTION_NEVER = 0;
- private static final int SHOW_AS_ACTION_IF_ROOM = 1;
- private static final int SHOW_AS_ACTION_ALWAYS = 2;
+
private int mShowAsAction = SHOW_AS_ACTION_NEVER;
/** Used for the icon resource ID if this item does not have an icon */
@@ -659,13 +653,7 @@ public final class MenuItemImpl implements MenuItem {
mFlags &= ~IS_ACTION;
}
}
-
- /**
- * Used by MenuInflater to set how this item should display in the presence of
- * an Action Bar.
- *
- * @param actionEnum Enum flag as defined in attrs.xml/SHOW_AS_ constants.
- */
+
public void setShowAsAction(int actionEnum) {
mShowAsAction = actionEnum;
mMenu.onItemActionRequestChanged(this);
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
new file mode 100644
index 000000000000..0ad4447e3cee
--- /dev/null
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -0,0 +1,272 @@
+/*
+ * 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 com.android.internal.widget;
+
+import com.android.internal.R;
+import com.android.internal.app.ActionBarImpl;
+
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+/**
+ * @hide
+ */
+public class ActionBarContextView extends ViewGroup {
+ // TODO: This must be defined in the default theme
+ private static final int CONTENT_HEIGHT_DIP = 50;
+
+ private int mItemPadding;
+ private int mItemMargin;
+ private int mContentHeight;
+
+ private CharSequence mTitle;
+ private CharSequence mSubtitle;
+
+ private ImageButton mCloseButton;
+ private View mCustomView;
+ private TextView mTitleView;
+ private Drawable mCloseDrawable;
+
+ public ActionBarContextView(Context context) {
+ this(context, null, 0);
+ }
+
+ public ActionBarContextView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ActionBarContextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ TypedArray a = context.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.Theme);
+ mItemPadding = a.getDimensionPixelOffset(
+ com.android.internal.R.styleable.Theme_actionButtonPadding, 0);
+ setBackgroundDrawable(a.getDrawable(
+ com.android.internal.R.styleable.Theme_actionBarContextBackground));
+ mCloseDrawable = a.getDrawable(
+ com.android.internal.R.styleable.Theme_actionBarCloseContextDrawable);
+ mItemMargin = mItemPadding / 2;
+
+ mContentHeight = CONTENT_HEIGHT_DIP;
+ a.recycle();
+ }
+
+ public void setCustomView(View view) {
+ if (mCustomView != null) {
+ removeView(mCustomView);
+ }
+ mCustomView = view;
+ if (mTitleView != null) {
+ removeView(mTitleView);
+ mTitleView = null;
+ }
+ if (view != null) {
+ addView(view);
+ }
+ requestLayout();
+ }
+
+ public void setTitle(CharSequence title) {
+ mTitle = title;
+ if (mTitleView == null) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ mTitleView = (TextView) inflater.inflate(R.layout.action_bar_title_item, null);
+ mTitleView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT));
+ if (title != null) {
+ mTitleView.setText(title);
+ }
+ addView(mTitleView);
+ } else {
+ mTitleView.setText(title);
+ if (mTitleView.getParent() == null) {
+ addView(mTitleView);
+ }
+ }
+ }
+
+ public void setSubtitle(CharSequence subtitle) {
+ mSubtitle = subtitle;
+ // TODO add subtitle support
+ }
+
+ public void initForMode(final ActionBar.ContextMode mode) {
+ final ActionBarImpl.ContextMode implMode = (ActionBarImpl.ContextMode) mode;
+
+ if (mCloseButton == null) {
+ mCloseButton = new ImageButton(getContext());
+ mCloseButton.setImageDrawable(mCloseDrawable);
+ mCloseButton.setBackgroundDrawable(null);
+ mCloseButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ mode.finish();
+ }
+ });
+ }
+ addView(mCloseButton);
+
+ final Context context = getContext();
+ final Menu menu = mode.getMenu();
+ final int itemCount = menu.size();
+ for (int i = 0; i < itemCount; i++) {
+ final MenuItem item = menu.getItem(i);
+ final ImageButton button = new ImageButton(context, null,
+ com.android.internal.R.attr.actionButtonStyle);
+ button.setClickable(true);
+ button.setFocusable(true);
+ button.setImageDrawable(item.getIcon());
+ button.setId(item.getItemId());
+ button.setVisibility(item.isVisible() ? VISIBLE : GONE);
+ button.setEnabled(item.isEnabled());
+
+ button.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ implMode.dispatchOnContextItemClicked(item);
+ }
+ });
+
+ addView(button);
+ }
+ requestLayout();
+ }
+
+ public void closeMode() {
+ removeAllViews();
+ mCustomView = null;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final 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)");
+ }
+
+ final 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\"");
+ }
+
+ final int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
+ final int itemMargin = mItemPadding;
+
+ int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight();
+ final int height = mContentHeight - getPaddingTop() - getPaddingBottom();
+ final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
+
+ if (mCloseButton != null) {
+ availableWidth = measureChildView(mCloseButton, availableWidth,
+ childSpecHeight, itemMargin);
+ }
+
+ if (mTitleView != null && mCustomView == null) {
+ availableWidth = measureChildView(mTitleView, availableWidth,
+ childSpecHeight, itemMargin);
+ }
+
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ if (child == mCloseButton || child == mTitleView || child == mCustomView) {
+ continue;
+ }
+
+ availableWidth = measureChildView(child, availableWidth, childSpecHeight, itemMargin);
+ }
+
+ if (mCustomView != null) {
+ mCustomView.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ }
+
+ setMeasuredDimension(contentWidth, mContentHeight);
+ }
+
+ @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();
+ final int itemMargin = mItemPadding;
+
+ if (mCloseButton != null && mCloseButton.getVisibility() != GONE) {
+ x += positionChild(mCloseButton, x, y, contentHeight);
+ }
+
+ if (mTitleView != null && mCustomView == null) {
+ x += positionChild(mTitleView, x, y, contentHeight) + itemMargin;
+ }
+
+ if (mCustomView != null) {
+ x += positionChild(mCustomView, x, y, contentHeight) + itemMargin;
+ }
+
+ x = r - l - getPaddingRight();
+
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ if (child == mCloseButton || child == mTitleView || child == mCustomView) {
+ continue;
+ }
+
+ x -= positionChildInverse(child, x, y, contentHeight) + itemMargin;
+ }
+ }
+
+ private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) {
+ child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
+ childSpecHeight);
+
+ availableWidth -= child.getMeasuredWidth();
+ availableWidth -= spacing;
+
+ return availableWidth;
+ }
+
+ 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;
+ }
+}
diff --git a/core/java/android/view/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 5142c50c8ad1..dcc1731b1a6a 100644
--- a/core/java/android/view/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -14,17 +14,16 @@
* limitations under the License.
*/
-package android.view;
+package com.android.internal.widget;
import com.android.internal.R;
-import com.android.internal.view.menu.ActionMenu;
import com.android.internal.view.menu.ActionMenuItem;
import com.android.internal.view.menu.ActionMenuView;
import com.android.internal.view.menu.MenuBuilder;
import android.app.ActionBar;
import android.app.Activity;
-import android.app.ActionBar.Callback;
+import android.app.ActionBar.NavigationCallback;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -34,7 +33,10 @@ import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
-import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.Spinner;
@@ -90,9 +92,7 @@ public class ActionBarView extends ViewGroup {
private ActionMenuItem mLogoNavItem;
- private SparseArray<ActionMenu> mContextMenus;
-
- private Callback mCallback;
+ private NavigationCallback mCallback;
private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
new AdapterView.OnItemSelectedListener() {
@@ -173,11 +173,9 @@ public class ActionBarView extends ViewGroup {
}
};
}
-
- mContextMenus = new SparseArray<ActionMenu>();
}
- public void setCallback(Callback callback) {
+ public void setCallback(NavigationCallback callback) {
mCallback = callback;
}
@@ -310,34 +308,6 @@ public class ActionBarView extends ViewGroup {
return mDisplayOptions;
}
- 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.
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/core/res/res/drawable/action_bar_context_background.xml b/core/res/res/drawable/action_bar_context_background.xml
new file mode 100644
index 000000000000..8789898186ec
--- /dev/null
+++ b/core/res/res/drawable/action_bar_context_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#ff000000"
+ android:centerColor="#ffd1d2d4"
+ android:endColor="#ff85878a"
+ android:angle="270" />
+</shape>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 01a4b429afe8..f39852b8d314 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -21,20 +21,30 @@ This is an optimized layout for a screen with the Action Bar enabled.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
- <ActionBarView android:id="@+id/action_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="?android:attr/windowActionBarStyle" />
+ <ViewAnimator android:id="@+id/action_bar_animator"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inAnimation="@anim/push_down_in"
+ android:outAnimation="@anim/push_down_out">
+ <com.android.internal.widget.ActionBarView
+ android:id="@+id/action_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="?android:attr/windowActionBarStyle" />
+ <com.android.internal.widget.ActionBarContextView
+ android:id="@+id/action_context_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </ViewAnimator>
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
- <LinearLayout android:id="@+id/context_action_bar"
+ <LinearLayout android:id="@+id/lower_action_context_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/windowActionBarStyle"
android:visibility="gone" />
</LinearLayout>
-
diff --git a/core/res/res/layout/screen_xlarge_action_bar.xml b/core/res/res/layout/screen_xlarge_action_bar.xml
new file mode 100644
index 000000000000..c51ca13031b5
--- /dev/null
+++ b/core/res/res/layout/screen_xlarge_action_bar.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!--
+This is an optimized layout for a screen with the Action Bar enabled.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:fitsSystemWindows="true">
+ <ViewAnimator android:id="@+id/action_bar_animator"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inAnimation="@anim/push_down_in"
+ android:outAnimation="@anim/push_down_out">
+ <com.android.internal.widget.ActionBarView
+ android:id="@+id/action_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="?android:attr/windowActionBarStyle" />
+ <com.android.internal.widget.ActionBarContextView
+ android:id="@+id/action_context_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </ViewAnimator>
+ <FrameLayout android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:foregroundGravity="fill_horizontal|top"
+ android:foreground="?android:attr/windowContentOverlay" />
+</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7470eca5fb56..b3f280b8919c 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -444,6 +444,8 @@
<eat-comment />
<!-- Default amount of padding to use between action buttons. -->
<attr name="actionButtonPadding" format="dimension" />
+ <attr name="actionBarContextBackground" format="reference" />
+ <attr name="actionBarCloseContextDrawable" format="reference" />
<!-- =================== -->
<!-- Preference styles -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e98c8afc9546..b9e5e8400aa1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1300,6 +1300,8 @@
<public type="attr" name="showAsAction" />
<public type="attr" name="actionButtonPadding" />
<public type="attr" name="previewImage" />
+ <public type="attr" name="actionBarContextBackground" />
+ <public type="attr" name="actionBarCloseContextDrawable" />
<public type="id" name="home" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 76bba4b14d32..2dfe9ab3b6f2 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -206,6 +206,8 @@
<!-- Action bar styles -->
<item name="actionButtonPadding">12dip</item>
+ <item name="actionBarContextBackground">@android:drawable/action_bar_context_background</item>
+ <item name="actionBarCloseContextDrawable">@android:drawable/ic_menu_close_clear_cancel</item>
</style>
<!-- Variant of the default (dark) theme with no title bar -->
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index e7511e0e1d82..5c56d3c42949 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -29,6 +29,7 @@ import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuDialogHelper;
import com.android.internal.view.menu.MenuView;
import com.android.internal.view.menu.SubMenuBuilder;
+import com.android.internal.widget.ActionBarView;
import android.app.KeyguardManager;
import android.app.SearchManager;
@@ -53,7 +54,6 @@ import android.util.Config;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
-import android.view.ActionBarView;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.InputQueue;
@@ -2224,7 +2224,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (mIsFloating) {
layoutResource = com.android.internal.R.layout.dialog_title;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
- layoutResource = com.android.internal.R.layout.screen_action_bar;
+ Configuration config = getContext().getResources().getConfiguration();
+ if ((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_XLARGE) ==
+ Configuration.SCREENLAYOUT_SIZE_XLARGE) {
+ layoutResource = com.android.internal.R.layout.screen_xlarge_action_bar;
+ } else {
+ layoutResource = com.android.internal.R.layout.screen_action_bar;
+ }
} else {
layoutResource = com.android.internal.R.layout.screen_title;
}