summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Powell <adamp@google.com>2011-08-30 17:40:40 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-08-30 17:40:40 -0700
commit38e1c7a8a614a491747d08f91aa6eceaee8123fb (patch)
tree1df233a7692c91675da5d48a0acc5571e4db87c8
parent256147581959868044bd92bad281c5c75a1068d7 (diff)
parent282e377d8b25a3aaf02ce40f33279d94b77ecbdc (diff)
downloadframeworks_base-38e1c7a8a614a491747d08f91aa6eceaee8123fb.zip
frameworks_base-38e1c7a8a614a491747d08f91aa6eceaee8123fb.tar.gz
frameworks_base-38e1c7a8a614a491747d08f91aa6eceaee8123fb.tar.bz2
Merge "Ellipsize marquee TextViews that aren't currently animating"
-rw-r--r--core/java/android/widget/TextView.java230
1 files changed, 159 insertions, 71 deletions
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 135797f..4ce2d90 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -64,6 +64,7 @@ import android.text.TextDirectionHeuristics;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.text.TextUtils.TruncateAt;
import android.text.method.AllCapsTransformationMethod;
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.DateKeyListener;
@@ -366,6 +367,35 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private boolean mResolvedDrawables = false;
+ /**
+ * On some devices the fading edges add a performance penalty if used
+ * extensively in the same layout. This mode indicates how the marquee
+ * is currently being shown, if applicable. (mEllipsize will == MARQUEE)
+ */
+ private int mMarqueeFadeMode = MARQUEE_FADE_NORMAL;
+
+ /**
+ * When mMarqueeFadeMode is not MARQUEE_FADE_NORMAL, this stores
+ * the layout that should be used when the mode switches.
+ */
+ private Layout mSavedMarqueeModeLayout;
+
+ /**
+ * Draw marquee text with fading edges as usual
+ */
+ private static final int MARQUEE_FADE_NORMAL = 0;
+
+ /**
+ * Draw marquee text as ellipsize end while inactive instead of with the fade.
+ * (Useful for devices where the fade can be expensive if overdone)
+ */
+ private static final int MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS = 1;
+
+ /**
+ * Draw marquee text with fading edges because it is currently active/animating.
+ */
+ private static final int MARQUEE_FADE_SWITCH_SHOW_FADE = 2;
+
/*
* Kick-start the font cache for the zygote process (to pay the cost of
* initializing freetype for our default font only once).
@@ -997,8 +1027,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setEllipsize(TextUtils.TruncateAt.END);
break;
case 4:
- setHorizontalFadingEdgeEnabled(
- ViewConfiguration.get(context).isFadingMarqueeEnabled());
+ if (ViewConfiguration.get(context).isFadingMarqueeEnabled()) {
+ setHorizontalFadingEdgeEnabled(true);
+ mMarqueeFadeMode = MARQUEE_FADE_NORMAL;
+ } else {
+ setHorizontalFadingEdgeEnabled(false);
+ mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+ }
setEllipsize(TextUtils.TruncateAt.MARQUEE);
break;
}
@@ -3069,8 +3104,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (text instanceof Spanned &&
((Spanned) text).getSpanStart(TextUtils.TruncateAt.MARQUEE) >= 0) {
- setHorizontalFadingEdgeEnabled(
- ViewConfiguration.get(mContext).isFadingMarqueeEnabled());
+ if (ViewConfiguration.get(mContext).isFadingMarqueeEnabled()) {
+ setHorizontalFadingEdgeEnabled(true);
+ mMarqueeFadeMode = MARQUEE_FADE_NORMAL;
+ } else {
+ setHorizontalFadingEdgeEnabled(false);
+ mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+ }
setEllipsize(TextUtils.TruncateAt.MARQUEE);
}
@@ -4763,7 +4803,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int layoutDirection = getResolvedLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
+ if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
(absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
canvas.translate(mLayout.getLineRight(0) - (mRight - mLeft -
@@ -5947,7 +5988,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mSavedHintLayout = (BoringLayout) mHintLayout;
}
- mLayout = mHintLayout = null;
+ mSavedMarqueeModeLayout = mLayout = mHintLayout = null;
// Since it depends on the value of mLayout
prepareCursorControllers();
@@ -6067,73 +6108,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Layout.Alignment alignment = getLayoutAlignment();
boolean shouldEllipsize = mEllipsize != null && mInput == null;
+ final boolean switchEllipsize = mEllipsize == TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_NORMAL;
+ TruncateAt effectiveEllipsize = mEllipsize;
+ if (mEllipsize == TruncateAt.MARQUEE &&
+ mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
+ effectiveEllipsize = TruncateAt.END;
+ }
if (mTextDir == null) {
resolveTextDirection();
}
- if (mText instanceof Spannable) {
- mLayout = new DynamicLayout(mText, mTransformed, mTextPaint, w,
- alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, mInput == null ? mEllipsize : null,
- ellipsisWidth);
- } else {
- if (boring == UNKNOWN_BORING) {
- boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
- if (boring != null) {
- mBoring = boring;
- }
- }
- if (boring != null) {
- if (boring.width <= w &&
- (mEllipsize == null || boring.width <= ellipsisWidth)) {
- if (mSavedLayout != null) {
- mLayout = mSavedLayout.
- replaceOrMake(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad);
- } else {
- mLayout = BoringLayout.make(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad);
- }
-
- mSavedLayout = (BoringLayout) mLayout;
- } else if (shouldEllipsize && boring.width <= w) {
- if (mSavedLayout != null) {
- mLayout = mSavedLayout.
- replaceOrMake(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad, mEllipsize,
- ellipsisWidth);
- } else {
- mLayout = BoringLayout.make(mTransformed, mTextPaint,
- w, alignment, mSpacingMult, mSpacingAdd,
- boring, mIncludePad, mEllipsize,
- ellipsisWidth);
- }
- } else if (shouldEllipsize) {
- mLayout = new StaticLayout(mTransformed,
- 0, mTransformed.length(),
- mTextPaint, w, alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
- } else {
- mLayout = new StaticLayout(mTransformed, mTextPaint,
- w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
- mIncludePad);
- }
- } else if (shouldEllipsize) {
- mLayout = new StaticLayout(mTransformed,
- 0, mTransformed.length(),
- mTextPaint, w, alignment, mTextDir, mSpacingMult,
- mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
- } else {
- mLayout = new StaticLayout(mTransformed, mTextPaint,
- w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
- mIncludePad);
- }
+ mLayout = makeSingleLayout(w, boring, ellipsisWidth, alignment, shouldEllipsize,
+ effectiveEllipsize, effectiveEllipsize == mEllipsize);
+ if (switchEllipsize) {
+ TruncateAt oppositeEllipsize = effectiveEllipsize == TruncateAt.MARQUEE ?
+ TruncateAt.END : TruncateAt.MARQUEE;
+ mSavedMarqueeModeLayout = makeSingleLayout(w, boring, ellipsisWidth, alignment,
+ shouldEllipsize, oppositeEllipsize, effectiveEllipsize != mEllipsize);
}
shouldEllipsize = mEllipsize != null;
@@ -6224,6 +6217,77 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
prepareCursorControllers();
}
+ private Layout makeSingleLayout(int w, BoringLayout.Metrics boring, int ellipsisWidth,
+ Layout.Alignment alignment, boolean shouldEllipsize, TruncateAt effectiveEllipsize,
+ boolean useSaved) {
+ Layout result = null;
+ if (mText instanceof Spannable) {
+ result = new DynamicLayout(mText, mTransformed, mTextPaint, w,
+ alignment, mTextDir, mSpacingMult,
+ mSpacingAdd, mIncludePad, mInput == null ? effectiveEllipsize : null,
+ ellipsisWidth);
+ } else {
+ if (boring == UNKNOWN_BORING) {
+ boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
+ if (boring != null) {
+ mBoring = boring;
+ }
+ }
+
+ if (boring != null) {
+ if (boring.width <= w &&
+ (effectiveEllipsize == null || boring.width <= ellipsisWidth)) {
+ if (useSaved && mSavedLayout != null) {
+ result = mSavedLayout.replaceOrMake(mTransformed, mTextPaint,
+ w, alignment, mSpacingMult, mSpacingAdd,
+ boring, mIncludePad);
+ } else {
+ result = BoringLayout.make(mTransformed, mTextPaint,
+ w, alignment, mSpacingMult, mSpacingAdd,
+ boring, mIncludePad);
+ }
+
+ if (useSaved) {
+ mSavedLayout = (BoringLayout) result;
+ }
+ } else if (shouldEllipsize && boring.width <= w) {
+ if (useSaved && mSavedLayout != null) {
+ result = mSavedLayout.replaceOrMake(mTransformed, mTextPaint,
+ w, alignment, mSpacingMult, mSpacingAdd,
+ boring, mIncludePad, effectiveEllipsize,
+ ellipsisWidth);
+ } else {
+ result = BoringLayout.make(mTransformed, mTextPaint,
+ w, alignment, mSpacingMult, mSpacingAdd,
+ boring, mIncludePad, effectiveEllipsize,
+ ellipsisWidth);
+ }
+ } else if (shouldEllipsize) {
+ result = new StaticLayout(mTransformed,
+ 0, mTransformed.length(),
+ mTextPaint, w, alignment, mTextDir, mSpacingMult,
+ mSpacingAdd, mIncludePad, effectiveEllipsize,
+ ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ } else {
+ result = new StaticLayout(mTransformed, mTextPaint,
+ w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
+ mIncludePad);
+ }
+ } else if (shouldEllipsize) {
+ result = new StaticLayout(mTransformed,
+ 0, mTransformed.length(),
+ mTextPaint, w, alignment, mTextDir, mSpacingMult,
+ mSpacingAdd, mIncludePad, effectiveEllipsize,
+ ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ } else {
+ result = new StaticLayout(mTransformed, mTextPaint,
+ w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
+ mIncludePad);
+ }
+ }
+ return result;
+ }
+
private boolean compressText(float width) {
if (isHardwareAccelerated()) return false;
@@ -7179,7 +7243,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private boolean canMarquee() {
int width = (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight());
- return width > 0 && mLayout.getLineWidth(0) > width;
+ return width > 0 && (mLayout.getLineWidth(0) > width ||
+ (mMarqueeFadeMode != MARQUEE_FADE_NORMAL && mSavedMarqueeModeLayout != null &&
+ mSavedMarqueeModeLayout.getLineWidth(0) > width));
}
private void startMarquee() {
@@ -7193,6 +7259,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if ((mMarquee == null || mMarquee.isStopped()) && (isFocused() || isSelected()) &&
getLineCount() == 1 && canMarquee()) {
+ if (mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
+ mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_FADE;
+ final Layout tmp = mLayout;
+ mLayout = mSavedMarqueeModeLayout;
+ mSavedMarqueeModeLayout = tmp;
+ setHorizontalFadingEdgeEnabled(true);
+ requestLayout();
+ invalidate();
+ }
+
if (mMarquee == null) mMarquee = new Marquee(this);
mMarquee.start(mMarqueeRepeatLimit);
}
@@ -7202,6 +7278,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mMarquee != null && !mMarquee.isStopped()) {
mMarquee.stop();
}
+
+ if (mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_FADE) {
+ mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+ final Layout tmp = mSavedMarqueeModeLayout;
+ mSavedMarqueeModeLayout = mLayout;
+ mLayout = tmp;
+ setHorizontalFadingEdgeEnabled(false);
+ requestLayout();
+ invalidate();
+ }
}
private void startStopMarquee(boolean start) {
@@ -8407,7 +8493,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected float getLeftFadingEdgeStrength() {
if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return 0.0f;
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
+ if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
if (mMarquee != null && !mMarquee.isStopped()) {
final Marquee marquee = mMarquee;
if (marquee.shouldDrawLeftFade()) {
@@ -8436,7 +8523,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
protected float getRightFadingEdgeStrength() {
if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return 0.0f;
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
+ if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
if (mMarquee != null && !mMarquee.isStopped()) {
final Marquee marquee = mMarquee;
return (marquee.mMaxFadeScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();