Add subtitles for action bars and context modes.
Fix an issue where context mode content was cleared before animating out.
Change-Id: Ie7a065e65bc18e3da32de07543d0f71d2a2d648c
diff --git a/api/current.xml b/api/current.xml
index 72630eb..f941780 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -19620,6 +19620,43 @@
<parameter name="title" type="java.lang.CharSequence">
</parameter>
</method>
+<method name="setStandardNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setSubtitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<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"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+</method>
<method name="startContextMode"
return="void"
abstract="true"
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 1775a0d..67133e0 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -103,7 +103,7 @@
* good for extended descriptions of activity state.
*
* @param title The action bar's title. null is treated as an empty string.
- * @param subtitle The action bar's subtitle. null is treated as an empty string.
+ * @param subtitle The action bar's subtitle. null will remove the subtitle entirely.
*/
public abstract void setStandardNavigationMode(CharSequence title, CharSequence subtitle);
@@ -111,13 +111,37 @@
* Set the action bar into standard navigation mode, supplying a title and subtitle.
*
* Standard navigation mode is default. The title is automatically set to the
- * name of your Activity.
+ * name of your Activity on startup if an action bar is present.
*
* @param title The action bar's title. null is treated as an empty string.
*/
public abstract void setStandardNavigationMode(CharSequence title);
/**
+ * Set the action bar into standard navigation mode, using the currently set title
+ * and/or subtitle.
+ *
+ * Standard navigation mode is default. The title is automatically set to the name of
+ * your Activity on startup if an action bar is present.
+ */
+ public abstract void setStandardNavigationMode();
+
+ /**
+ * Set the action bar's title. This will only be displayed in standard navigation mode.
+ *
+ * @param title Title to set
+ */
+ public abstract void setTitle(CharSequence title);
+
+ /**
+ * Set the action bar's subtitle. This will only be displayed in standard navigation mode.
+ * Set to null to disable the subtitle entirely.
+ *
+ * @param subtitle Subtitle to set
+ */
+ public abstract void setSubtitle(CharSequence subtitle);
+
+ /**
* Set display options. This changes all display option bits at once. To change
* a limited subset of display options, see {@link #setDisplayOptions(int, int)}.
*
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index b36524e..6ac68aa 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -23,6 +23,7 @@
import android.app.ActionBar;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -52,7 +53,17 @@
private static final int CONTEXT_DISPLAY_SPLIT = 1;
private int mContextDisplayMode;
-
+
+ final Handler mHandler = new Handler();
+ final Runnable mCloseContext = new Runnable() {
+ public void run() {
+ mUpperContextView.closeMode();
+ if (mLowerContextView != null) {
+ mLowerContextView.removeAllViews();
+ }
+ }
+ };
+
public ActionBarImpl(View decor) {
mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
mUpperContextView = (ActionBarContextView) decor.findViewById(
@@ -66,7 +77,7 @@
throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
"with a compatible window decor layout");
}
-
+
mContextDisplayMode = mLowerContextView == null ?
CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
}
@@ -75,17 +86,22 @@
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() {
+ mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
+ mActionView.setCallback(null);
+ }
+
public void setStandardNavigationMode(CharSequence title) {
setStandardNavigationMode(title, null);
}
-
+
public void setStandardNavigationMode(CharSequence title, CharSequence subtitle) {
mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
mActionView.setTitle(title);
@@ -93,10 +109,18 @@
mActionView.setCallback(null);
}
+ 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));
@@ -170,11 +194,11 @@
@Override
public void finish() {
mCallback.onDestroyContextMode(this);
- mUpperContextView.closeMode();
- if (mLowerContextView != null) {
- mLowerContextView.removeAllViews();
- }
mAnimatorView.setDisplayedChild(NORMAL_VIEW);
+
+ // Clear out the context mode views after the animation finishes
+ mHandler.postDelayed(mCloseContext, mAnimatorView.getOutAnimation().getDuration());
+
if (mLowerContextView != null && mLowerContextView.getVisibility() != View.GONE) {
// TODO Animate this
mLowerContextView.setVisibility(View.GONE);
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 0ad4447..848e92e 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -29,6 +29,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
+import android.widget.LinearLayout;
import android.widget.TextView;
/**
@@ -47,7 +48,9 @@
private ImageButton mCloseButton;
private View mCustomView;
+ private LinearLayout mTitleLayout;
private TextView mTitleView;
+ private TextView mSubtitleView;
private Drawable mCloseDrawable;
public ActionBarContextView(Context context) {
@@ -80,40 +83,48 @@
removeView(mCustomView);
}
mCustomView = view;
- if (mTitleView != null) {
- removeView(mTitleView);
- mTitleView = null;
+ if (mTitleLayout != null) {
+ removeView(mTitleLayout);
+ mTitleLayout = null;
}
if (view != null) {
addView(view);
}
requestLayout();
}
-
+
public void setTitle(CharSequence title) {
mTitle = title;
- if (mTitleView == null) {
+ initTitle();
+ }
+
+ public void setSubtitle(CharSequence subtitle) {
+ mSubtitle = subtitle;
+ initTitle();
+ }
+
+ private void initTitle() {
+ if (mTitleLayout == 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);
+ mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
+ mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
+ mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
+ if (mTitle != null) {
+ mTitleView.setText(mTitle);
}
- addView(mTitleView);
+ if (mSubtitle != null) {
+ mSubtitleView.setText(mSubtitle);
+ }
+ addView(mTitleLayout);
} else {
- mTitleView.setText(title);
- if (mTitleView.getParent() == null) {
- addView(mTitleView);
+ mTitleView.setText(mTitle);
+ mSubtitleView.setText(mSubtitle);
+ if (mTitleLayout.getParent() == null) {
+ addView(mTitleLayout);
}
}
}
-
- 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;
@@ -148,17 +159,17 @@
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);
@@ -185,15 +196,15 @@
childSpecHeight, itemMargin);
}
- if (mTitleView != null && mCustomView == null) {
- availableWidth = measureChildView(mTitleView, availableWidth,
+ if (mTitleLayout != null && mCustomView == null) {
+ availableWidth = measureChildView(mTitleLayout, 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) {
+ if (child == mCloseButton || child == mTitleLayout || child == mCustomView) {
continue;
}
@@ -219,8 +230,8 @@
x += positionChild(mCloseButton, x, y, contentHeight);
}
- if (mTitleView != null && mCustomView == null) {
- x += positionChild(mTitleView, x, y, contentHeight) + itemMargin;
+ if (mTitleLayout != null && mCustomView == null) {
+ x += positionChild(mTitleLayout, x, y, contentHeight) + itemMargin;
}
if (mCustomView != null) {
@@ -232,7 +243,7 @@
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
- if (child == mCloseButton || child == mTitleView || child == mCustomView) {
+ if (child == mCloseButton || child == mTitleLayout || child == mCustomView) {
continue;
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index dcc1731..dcfdced 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -39,6 +39,7 @@
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
@@ -80,6 +81,7 @@
private ImageView mIconView;
private ImageView mLogoView;
+ private LinearLayout mTitleLayout;
private TextView mTitleView;
private TextView mSubtitleView;
private Spinner mSpinner;
@@ -250,9 +252,11 @@
if (mode != oldMode) {
switch (oldMode) {
case ActionBar.NAVIGATION_MODE_STANDARD:
- if (mTitleView != null) {
- removeView(mTitleView);
+ if (mTitleLayout != null) {
+ removeView(mTitleLayout);
+ mTitleLayout = null;
mTitleView = null;
+ mSubtitleView = null;
}
break;
case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
@@ -361,13 +365,17 @@
private void initTitle() {
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));
+ mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
+ mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
+ mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
if (mTitle != null) {
mTitleView.setText(mTitle);
}
- addView(mTitleView);
+ if (mSubtitle != null) {
+ mSubtitleView.setText(mSubtitle);
+ mSubtitleView.setVisibility(VISIBLE);
+ }
+ addView(mTitleLayout);
}
@Override
@@ -404,8 +412,8 @@
switch (mNavigationMode) {
case ActionBar.NAVIGATION_MODE_STANDARD:
- if (mTitleView != null) {
- measureChildView(mTitleView, availableWidth, childSpecHeight, mSpacing);
+ if (mTitleLayout != null) {
+ measureChildView(mTitleLayout, availableWidth, childSpecHeight, mSpacing);
}
break;
case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
@@ -452,8 +460,8 @@
switch (mNavigationMode) {
case ActionBar.NAVIGATION_MODE_STANDARD:
- if (mTitleView != null) {
- x += positionChild(mTitleView, x, y, contentHeight) + mSpacing;
+ if (mTitleLayout != null) {
+ x += positionChild(mTitleLayout, x, y, contentHeight) + mSpacing;
}
break;
case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index d7f7c13..3c046fe 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -14,9 +14,20 @@
limitations under the License.
-->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
-
- android:singleLine="true"
- android:ellipsize="end"
- android:textAppearance="?android:attr/textAppearanceMediumInverse" />
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+ <TextView android:id="@+id/action_bar_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceMediumInverse" />
+ <TextView android:id="@+id/action_bar_subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceSmallInverse" />
+</LinearLayout>