summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorFabrice Di Meglio <fdimeglio@google.com>2011-08-10 16:31:58 -0700
committerFabrice Di Meglio <fdimeglio@google.com>2011-08-15 13:18:34 -0700
commit8059e0903e36cbb5cf8b5c5d5d653acc9bbc8402 (patch)
treefba90001b825ca2d8c7102659d915b02caa3b7b9 /core/java
parentb2a85b69ce98a312c450849dfd18bd1f878b5d66 (diff)
downloadframeworks_base-8059e0903e36cbb5cf8b5c5d5d653acc9bbc8402.zip
frameworks_base-8059e0903e36cbb5cf8b5c5d5d653acc9bbc8402.tar.gz
frameworks_base-8059e0903e36cbb5cf8b5c5d5d653acc9bbc8402.tar.bz2
Fix bug #3388534 Long file names are improperly displayed when played
- force ellipsising when there are more lines found than maxLines - do not care about lines when we have reached maxLines - also fix relayouting when changing maxLines thru setMaxLines() - do not allow START / MIDDLE ellipsis when there are multiple lines (and print a log accordingly) Change-Id: I90f5a7f5200a220aceee01fb7300bec2c4c3a075
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/text/DynamicLayout.java5
-rw-r--r--core/java/android/text/Layout.java15
-rw-r--r--core/java/android/text/StaticLayout.java133
-rw-r--r--core/java/android/text/TextLine.java3
-rw-r--r--core/java/android/widget/TextView.java56
5 files changed, 124 insertions, 88 deletions
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 2c78679..2f9852d 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -275,7 +275,7 @@ extends Layout
}
if (reflowed == null) {
- reflowed = new StaticLayout(true);
+ reflowed = new StaticLayout(getText());
} else {
reflowed.prepare();
}
@@ -488,7 +488,8 @@ extends Layout
private int mTopPadding, mBottomPadding;
- private static StaticLayout sStaticLayout = new StaticLayout(true);
+ private static StaticLayout sStaticLayout = null;
+
private static final Object[] sLock = new Object[0];
private static final int START = 0;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index eabeef0..421e995 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -880,6 +880,10 @@ public abstract class Layout {
}
}
Directions directions = getLineDirections(line);
+ // Returned directions can actually be null
+ if (directions == null) {
+ return 0f;
+ }
int dir = getParagraphDirection(line);
TextLine tl = TextLine.obtain();
@@ -1781,17 +1785,6 @@ public abstract class Layout {
}
}
- /**
- * Inform this layout that not all of its lines will be displayed, because a maximum number of
- * lines has been set on the associated TextView.
- *
- * A non strictly positive value means that all lines are displayed.
- *
- * @param lineCount number of visible lines
- * @hide
- */
- public void setMaximumVisibleLineCount(int lineCount) {}
-
private CharSequence mText;
private TextPaint mPaint;
/* package */ TextPaint mWorkPaint;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 14c71b2..788711d 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -23,6 +23,7 @@ import android.text.style.LeadingMarginSpan.LeadingMarginSpan2;
import android.text.style.LineHeightSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.TabStopSpan;
+import android.util.Log;
import com.android.internal.util.ArrayUtils;
@@ -38,6 +39,8 @@ import com.android.internal.util.ArrayUtils;
*/
public class StaticLayout extends Layout {
+ static final String TAG = "StaticLayout";
+
public StaticLayout(CharSequence source, TextPaint paint,
int width,
Alignment align, float spacingmult, float spacingadd,
@@ -75,7 +78,7 @@ public class StaticLayout extends Layout {
float spacingmult, float spacingadd,
boolean includepad) {
this(source, bufstart, bufend, paint, outerwidth, align, textDir,
- spacingmult, spacingadd, includepad, null, 0);
+ spacingmult, spacingadd, includepad, null, 0, Integer.MAX_VALUE);
}
public StaticLayout(CharSequence source, int bufstart, int bufend,
@@ -86,7 +89,7 @@ public class StaticLayout extends Layout {
TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
this(source, bufstart, bufend, paint, outerwidth, align,
TextDirectionHeuristics.FIRSTSTRONG_LTR,
- spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth);
+ spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth, Integer.MAX_VALUE);
}
/**
@@ -97,7 +100,7 @@ public class StaticLayout extends Layout {
Alignment align, TextDirectionHeuristic textDir,
float spacingmult, float spacingadd,
boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
+ TextUtils.TruncateAt ellipsize, int ellipsizedWidth, int maxLines) {
super((ellipsize == null)
? source
: (source instanceof Spanned)
@@ -130,6 +133,7 @@ public class StaticLayout extends Layout {
mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
mLineDirections = new Directions[
ArrayUtils.idealIntArraySize(2 * mColumns)];
+ mMaximumVisibleLineCount = maxLines;
mMeasured = MeasuredText.obtain();
@@ -141,8 +145,8 @@ public class StaticLayout extends Layout {
mFontMetricsInt = null;
}
- /* package */ StaticLayout(boolean ellipsize) {
- super(null, null, 0, null, 0, 0);
+ /* package */ StaticLayout(CharSequence text) {
+ super(text, null, 0, null, 0, 0);
mColumns = COLUMNS_ELLIPSIZE;
mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
@@ -394,6 +398,7 @@ public class StaticLayout extends Layout {
okBottom = fitBottom;
}
} else {
+ final boolean moreChars = (j + 1 < spanEnd);
if (ok != here) {
// Log.e("text", "output ok " + here + " to " +ok);
@@ -411,7 +416,7 @@ public class StaticLayout extends Layout {
ok == bufEnd, includepad, trackpad,
chs, widths, paraStart,
ellipsize, ellipsizedWidth, okWidth,
- paint);
+ paint, moreChars);
here = ok;
} else if (fit != here) {
@@ -427,7 +432,7 @@ public class StaticLayout extends Layout {
fit == bufEnd, includepad, trackpad,
chs, widths, paraStart,
ellipsize, ellipsizedWidth, fitWidth,
- paint);
+ paint, moreChars);
here = fit;
} else {
@@ -449,7 +454,7 @@ public class StaticLayout extends Layout {
trackpad,
chs, widths, paraStart,
ellipsize, ellipsizedWidth,
- widths[here - paraStart], paint);
+ widths[here - paraStart], paint, moreChars);
here = here + 1;
}
@@ -472,10 +477,13 @@ public class StaticLayout extends Layout {
width = restWidth;
}
}
+ if (mLineCount >= mMaximumVisibleLineCount) {
+ break;
+ }
}
}
- if (paraEnd != here) {
+ if (paraEnd != here && mLineCount < mMaximumVisibleLineCount) {
if ((fitTop | fitBottom | fitDescent | fitAscent) == 0) {
paint.getFontMetricsInt(fm);
@@ -496,7 +504,7 @@ public class StaticLayout extends Layout {
needMultiply, paraStart, chdirs, dir, easy,
paraEnd == bufEnd, includepad, trackpad,
chs, widths, paraStart,
- ellipsize, ellipsizedWidth, w, paint);
+ ellipsize, ellipsizedWidth, w, paint, paraEnd != bufEnd);
}
paraStart = paraEnd;
@@ -505,7 +513,8 @@ public class StaticLayout extends Layout {
break;
}
- if (bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) {
+ if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) &&
+ mLineCount < mMaximumVisibleLineCount) {
// Log.e("text", "output last " + bufEnd);
paint.getFontMetricsInt(fm);
@@ -519,7 +528,7 @@ public class StaticLayout extends Layout {
needMultiply, bufEnd, null, DEFAULT_DIR, true,
true, includepad, trackpad,
null, null, bufStart,
- ellipsize, ellipsizedWidth, 0, paint);
+ ellipsize, ellipsizedWidth, 0, paint, false);
}
}
@@ -624,7 +633,7 @@ public class StaticLayout extends Layout {
boolean includePad, boolean trackPad,
char[] chs, float[] widths, int widthStart,
TextUtils.TruncateAt ellipsize, float ellipsisWidth,
- float textWidth, TextPaint paint) {
+ float textWidth, TextPaint paint, boolean moreChars) {
int j = mLineCount;
int off = j * mColumns;
int want = off + mColumns + TOP;
@@ -722,9 +731,10 @@ public class StaticLayout extends Layout {
// If ellipsize is in marquee mode, do not apply ellipsis on the first line
if (ellipsize != null && (ellipsize != TextUtils.TruncateAt.MARQUEE || j != 0)) {
+ boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount);
calculateEllipsis(start, end, widths, widthStart,
ellipsisWidth, ellipsize, j,
- textWidth, paint);
+ textWidth, paint, forceEllipsis);
}
mLineCount++;
@@ -734,9 +744,9 @@ public class StaticLayout extends Layout {
private void calculateEllipsis(int lineStart, int lineEnd,
float[] widths, int widthStart,
float avail, TextUtils.TruncateAt where,
- int line, float textWidth, TextPaint paint) {
-
- if (textWidth <= avail) {
+ int line, float textWidth, TextPaint paint,
+ boolean forceEllipsis) {
+ if (textWidth <= avail && !forceEllipsis) {
// Everything fits!
mLines[mColumns * line + ELLIPSIS_START] = 0;
mLines[mColumns * line + ELLIPSIS_COUNT] = 0;
@@ -744,25 +754,33 @@ public class StaticLayout extends Layout {
}
float ellipsisWidth = paint.measureText(HORIZONTAL_ELLIPSIS);
- int ellipsisStart, ellipsisCount;
+ int ellipsisStart = 0;
+ int ellipsisCount = 0;
int len = lineEnd - lineStart;
+ // We only support start ellipsis on a single line
if (where == TextUtils.TruncateAt.START) {
- float sum = 0;
- int i;
+ if (mMaximumVisibleLineCount == 1) {
+ float sum = 0;
+ int i;
- for (i = len; i >= 0; i--) {
- float w = widths[i - 1 + lineStart - widthStart];
+ for (i = len; i >= 0; i--) {
+ float w = widths[i - 1 + lineStart - widthStart];
- if (w + sum + ellipsisWidth > avail) {
- break;
+ if (w + sum + ellipsisWidth > avail) {
+ break;
+ }
+
+ sum += w;
}
- sum += w;
+ ellipsisStart = 0;
+ ellipsisCount = i;
+ } else {
+ if (Log.isLoggable(TAG, Log.WARN)) {
+ Log.w(TAG, "Start Ellipsis only supported with one line");
+ }
}
-
- ellipsisStart = 0;
- ellipsisCount = i;
} else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE) {
float sum = 0;
int i;
@@ -779,34 +797,45 @@ public class StaticLayout extends Layout {
ellipsisStart = i;
ellipsisCount = len - i;
- } else /* where = TextUtils.TruncateAt.MIDDLE */ {
- float lsum = 0, rsum = 0;
- int left = 0, right = len;
+ if (forceEllipsis && ellipsisCount == 0 && i > 0) {
+ ellipsisStart = i - 1;
+ ellipsisCount = 1;
+ }
+ } else {
+ // where = TextUtils.TruncateAt.MIDDLE We only support middle ellipsis on a single line
+ if (mMaximumVisibleLineCount == 1) {
+ float lsum = 0, rsum = 0;
+ int left = 0, right = len;
- float ravail = (avail - ellipsisWidth) / 2;
- for (right = len; right >= 0; right--) {
- float w = widths[right - 1 + lineStart - widthStart];
+ float ravail = (avail - ellipsisWidth) / 2;
+ for (right = len; right >= 0; right--) {
+ float w = widths[right - 1 + lineStart - widthStart];
- if (w + rsum > ravail) {
- break;
+ if (w + rsum > ravail) {
+ break;
+ }
+
+ rsum += w;
}
- rsum += w;
- }
+ float lavail = avail - ellipsisWidth - rsum;
+ for (left = 0; left < right; left++) {
+ float w = widths[left + lineStart - widthStart];
- float lavail = avail - ellipsisWidth - rsum;
- for (left = 0; left < right; left++) {
- float w = widths[left + lineStart - widthStart];
+ if (w + lsum > lavail) {
+ break;
+ }
- if (w + lsum > lavail) {
- break;
+ lsum += w;
}
- lsum += w;
+ ellipsisStart = left;
+ ellipsisCount = right - left;
+ } else {
+ if (Log.isLoggable(TAG, Log.WARN)) {
+ Log.w(TAG, "Middle Ellipsis only supported with one line");
+ }
}
-
- ellipsisStart = left;
- ellipsisCount = right - left;
}
mLines[mColumns * line + ELLIPSIS_START] = ellipsisStart;
@@ -916,14 +945,6 @@ public class StaticLayout extends Layout {
return mEllipsizedWidth;
}
- /**
- * @hide
- */
- @Override
- public void setMaximumVisibleLineCount(int lineCount) {
- mMaximumVisibleLineCount = lineCount;
- }
-
void prepare() {
mMeasured = MeasuredText.obtain();
}
@@ -949,7 +970,7 @@ public class StaticLayout extends Layout {
private int[] mLines;
private Directions[] mLineDirections;
- private int mMaximumVisibleLineCount = 0;
+ private int mMaximumVisibleLineCount = Integer.MAX_VALUE;
private static final int START_MASK = 0x1FFFFFFF;
private static final int DIR_SHIFT = 30;
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 376e4f5..fcc372e 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -125,6 +125,9 @@ class TextLine {
mLen = limit - start;
mDir = dir;
mDirections = directions;
+ if (mDirections == null) {
+ throw new IllegalArgumentException("Directions cannot be null");
+ }
mHasTabs = hasTabs;
mSpanned = null;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1ab1a87..d1a5196 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6068,6 +6068,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int ellipsisWidth, boolean bringIntoView) {
stopMarquee();
+ // Update "old" cached values
+ mOldMaximum = mMaximum;
+ mOldMaxMode = mMaxMode;
+
mHighlightPathBogus = true;
if (w < 0) {
@@ -6129,7 +6133,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
0, mTransformed.length(),
mTextPaint, w, alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth);
+ ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
} else {
mLayout = new StaticLayout(mTransformed, mTextPaint,
w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
@@ -6140,7 +6144,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
0, mTransformed.length(),
mTextPaint, w, alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth);
+ ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
} else {
mLayout = new StaticLayout(mTransformed, mTextPaint,
w, alignment, mTextDir, mSpacingMult, mSpacingAdd,
@@ -6195,7 +6199,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
0, mHint.length(),
mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth);
+ ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
} else {
mHintLayout = new StaticLayout(mHint, mTextPaint,
hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
@@ -6206,7 +6210,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
0, mHint.length(),
mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
mSpacingAdd, mIncludePad, mEllipsize,
- ellipsisWidth);
+ ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
} else {
mHintLayout = new StaticLayout(mHint, mTextPaint,
hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
@@ -6411,25 +6415,34 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mHorizontallyScrolling) want = VERY_WIDE;
int hintWant = want;
- int hintWidth = mHintLayout == null ? hintWant : mHintLayout.getWidth();
+ int hintWidth = (mHintLayout == null) ? hintWant : mHintLayout.getWidth();
if (mLayout == null) {
makeNewLayout(want, hintWant, boring, hintBoring,
width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false);
- } else if ((mLayout.getWidth() != want) || (hintWidth != hintWant) ||
- (mLayout.getEllipsizedWidth() !=
- width - getCompoundPaddingLeft() - getCompoundPaddingRight())) {
- if (mHint == null && mEllipsize == null &&
- want > mLayout.getWidth() &&
- (mLayout instanceof BoringLayout ||
- (fromexisting && des >= 0 && des <= want))) {
- mLayout.increaseWidthTo(want);
+ } else {
+ final boolean layoutChanged = (mLayout.getWidth() != want) ||
+ (hintWidth != hintWant) ||
+ (mLayout.getEllipsizedWidth() !=
+ width - getCompoundPaddingLeft() - getCompoundPaddingRight());
+
+ final boolean widthChanged = (mHint == null) &&
+ (mEllipsize == null) &&
+ (want > mLayout.getWidth()) &&
+ (mLayout instanceof BoringLayout || (fromexisting && des >= 0 && des <= want));
+
+ final boolean maximumChanged = (mMaxMode != mOldMaxMode) || (mMaximum != mOldMaximum);
+
+ if (layoutChanged || maximumChanged) {
+ if (!maximumChanged && widthChanged) {
+ mLayout.increaseWidthTo(want);
+ } else {
+ makeNewLayout(want, hintWant, boring, hintBoring,
+ width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false);
+ }
} else {
- makeNewLayout(want, hintWant, boring, hintBoring,
- width - getCompoundPaddingLeft() - getCompoundPaddingRight(), false);
+ // Nothing has changed
}
- } else {
- // Width has not changed.
}
if (heightMode == MeasureSpec.EXACTLY) {
@@ -6489,7 +6502,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
desired += pad;
- layout.setMaximumVisibleLineCount(0);
if (mMaxMode == LINES) {
/*
@@ -6498,7 +6510,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
if (cap) {
if (linecount > mMaximum) {
- layout.setMaximumVisibleLineCount(mMaximum);
desired = layout.getLineTop(mMaximum);
if (dr != null) {
@@ -7106,6 +7117,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* to constrain the text to a single line. Use <code>null</code>
* to turn off ellipsizing.
*
+ * If {@link #setMaxLines} has been used to set two or more lines,
+ * {@link TextUtils.TruncateAt#END} and {@link TextUtils.TruncateAt#MARQUEE}
+ * are only supported (other ellipsizing types will not do anything).
+ *
* @attr ref android.R.styleable#TextView_ellipsize
*/
public void setEllipsize(TextUtils.TruncateAt where) {
@@ -10878,6 +10893,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private int mMinimum = 0;
private int mMinMode = LINES;
+ private int mOldMaximum = mMaximum;
+ private int mOldMaxMode = mMaxMode;
+
private int mMaxWidth = Integer.MAX_VALUE;
private int mMaxWidthMode = PIXELS;
private int mMinWidth = 0;