Add support for optional titles in action modes
Optional titles will only be displayed in the CAB if they entirely fit
instead of ellipsizing.
Fixes bug 5821883
Change-Id: I0cfd6d4fd34a4fa9f520499d577706da30606811
diff --git a/api/current.txt b/api/current.txt
index e0dad49..c43c45f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21935,12 +21935,14 @@
method public java.lang.Object getTag();
method public abstract java.lang.CharSequence getTitle();
method public abstract void invalidate();
+ method public boolean isTitleOptional();
method public abstract void setCustomView(android.view.View);
method public abstract void setSubtitle(java.lang.CharSequence);
method public abstract void setSubtitle(int);
method public void setTag(java.lang.Object);
method public abstract void setTitle(java.lang.CharSequence);
method public abstract void setTitle(int);
+ method public void setTitleOptionalHint(boolean);
}
public static abstract interface ActionMode.Callback {
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
index 220214b..5696839 100644
--- a/core/java/android/inputmethodservice/ExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -124,6 +124,12 @@
}
@Override
+ public boolean isTitleOptional() {
+ // Not only is it optional, it will *never* be shown.
+ return true;
+ }
+
+ @Override
public void setCustomView(View view) {
// Custom view is not supported here.
}
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index c1c7fe2..0ba5fdb 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -104,6 +104,32 @@
public abstract void setSubtitle(int resId);
/**
+ * Set whether or not the title/subtitle display for this action mode
+ * is optional.
+ *
+ * <p>In many cases the supplied title for an action mode is merely
+ * meant to add context and is not strictly required for the action
+ * mode to be useful. If the title is optional, the system may choose
+ * to hide the title entirely rather than truncate it due to a lack
+ * of available space.</p>
+ *
+ * <p>Note that this is merely a hint; the underlying implementation
+ * may choose to ignore this setting under some circumstances.</p>
+ *
+ * @param titleOptional true if the title only presents optional information.
+ */
+ public void setTitleOptionalHint(boolean titleOptional) {
+ }
+
+ /**
+ * @return true if this action mode considers the title and subtitle fields
+ * as optional. Optional titles may not be displayed to the user.
+ */
+ public boolean isTitleOptional() {
+ return false;
+ }
+
+ /**
* Set a custom view for this action mode. The custom view will take the place of
* the title and subtitle. Useful for things like search boxes.
*
diff --git a/core/java/android/webkit/SelectActionModeCallback.java b/core/java/android/webkit/SelectActionModeCallback.java
index cdf20f6..2a770f5 100644
--- a/core/java/android/webkit/SelectActionModeCallback.java
+++ b/core/java/android/webkit/SelectActionModeCallback.java
@@ -53,10 +53,8 @@
mode.getMenuInflater().inflate(com.android.internal.R.menu.webview_copy, menu);
final Context context = mWebView.getContext();
- boolean allowText = context.getResources().getBoolean(
- com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
- mode.setTitle(allowText ?
- context.getString(com.android.internal.R.string.textSelectionCABTitle) : null);
+ mode.setTitle(context.getString(com.android.internal.R.string.textSelectionCABTitle));
+ mode.setTitleOptionalHint(true);
// If the action mode UI we're running in isn't capable of taking window focus
// the user won't be able to type into the find on page UI. Disable this functionality.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a4087d5..1620929 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10363,9 +10363,9 @@
boolean allowText = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
- mode.setTitle(allowText ?
- mContext.getString(com.android.internal.R.string.textSelectionCABTitle) : null);
+ mode.setTitle(mContext.getString(com.android.internal.R.string.textSelectionCABTitle));
mode.setSubtitle(null);
+ mode.setTitleOptionalHint(true);
int selectAllIconId = 0; // No icon by default
if (!allowText) {
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index afb5bf1..f3486bd 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -748,6 +748,16 @@
}
@Override
+ public void setTitleOptionalHint(boolean titleOptional) {
+ mContextView.setTitleOptional(titleOptional);
+ }
+
+ @Override
+ public boolean isTitleOptional() {
+ return mContextView.isTitleOptional();
+ }
+
+ @Override
public View getCustomView() {
return mCustomView != null ? mCustomView.get() : null;
}
diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java
index edf4443..4b681ec 100644
--- a/core/java/com/android/internal/view/StandaloneActionMode.java
+++ b/core/java/com/android/internal/view/StandaloneActionMode.java
@@ -72,6 +72,16 @@
}
@Override
+ public void setTitleOptionalHint(boolean titleOptional) {
+ mContextView.setTitleOptional(titleOptional);
+ }
+
+ @Override
+ public boolean isTitleOptional() {
+ return mContextView.isTitleOptional();
+ }
+
+ @Override
public void setCustomView(View view) {
mContextView.setCustomView(view);
mCustomView = view != null ? new WeakReference<View>(view) : null;
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index fa16527..16f08f5 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -56,6 +56,7 @@
private int mTitleStyleRes;
private int mSubtitleStyleRes;
private Drawable mSplitBackground;
+ private boolean mTitleOptional;
private Animator mCurrentAnimation;
private boolean mAnimateInOnLayout;
@@ -354,7 +355,18 @@
}
if (mTitleLayout != null && mCustomView == null) {
- availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
+ if (mTitleOptional) {
+ final int titleWidthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ mTitleLayout.measure(titleWidthSpec, childSpecHeight);
+ final int titleWidth = mTitleLayout.getMeasuredWidth();
+ final boolean titleFits = titleWidth <= availableWidth;
+ if (titleFits) {
+ availableWidth -= titleWidth;
+ }
+ mTitleLayout.setVisibility(titleFits ? VISIBLE : GONE);
+ } else {
+ availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
+ }
}
if (mCustomView != null) {
@@ -460,7 +472,7 @@
}
}
- if (mTitleLayout != null && mCustomView == null) {
+ if (mTitleLayout != null && mCustomView == null && mTitleLayout.getVisibility() != GONE) {
x += positionChild(mTitleLayout, x, y, contentHeight);
}
@@ -512,4 +524,15 @@
super.onInitializeAccessibilityEvent(event);
}
}
+
+ public void setTitleOptional(boolean titleOptional) {
+ if (titleOptional != mTitleOptional) {
+ requestLayout();
+ }
+ mTitleOptional = titleOptional;
+ }
+
+ public boolean isTitleOptional() {
+ return mTitleOptional;
+ }
}