summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/text/Layout.java11
-rw-r--r--core/java/android/text/StaticLayout.java85
-rw-r--r--core/java/android/widget/TextView.java45
3 files changed, 90 insertions, 51 deletions
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index f9afcc7ac36c..fd6fc7dc0860 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -634,6 +634,17 @@ public abstract class Layout {
}
/**
+ * Return the total height of this layout.
+ *
+ * @param cap if true and max lines is set, returns the height of the layout at the max lines.
+ *
+ * @hide
+ */
+ public int getHeight(boolean cap) {
+ return getHeight();
+ }
+
+ /**
* Return the base alignment of this layout.
*/
public final Alignment getAlignment() {
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index bdbe8b0f9a24..081be3afd6d3 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -836,7 +836,7 @@ public class StaticLayout extends Layout {
here = endPos;
breakIndex++;
- if (mLineCount >= mMaximumVisibleLineCount) {
+ if (mLineCount >= mMaximumVisibleLineCount && mEllipsized) {
return;
}
}
@@ -920,7 +920,25 @@ public class StaticLayout extends Layout {
boolean firstLine = (j == 0);
boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount);
- boolean lastLine = currentLineIsTheLastVisibleOne || (end == bufEnd);
+
+ if (ellipsize != null) {
+ // If there is only one line, then do any type of ellipsis except when it is MARQUEE
+ // if there are multiple lines, just allow END ellipsis on the last line
+ boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount);
+
+ boolean doEllipsis =
+ (((mMaximumVisibleLineCount == 1 && moreChars) || (firstLine && !moreChars)) &&
+ ellipsize != TextUtils.TruncateAt.MARQUEE) ||
+ (!firstLine && (currentLineIsTheLastVisibleOne || !moreChars) &&
+ ellipsize == TextUtils.TruncateAt.END);
+ if (doEllipsis) {
+ calculateEllipsis(start, end, widths, widthStart,
+ ellipsisWidth, ellipsize, j,
+ textWidth, paint, forceEllipsis);
+ }
+ }
+
+ boolean lastLine = mEllipsized || (end == bufEnd);
if (firstLine) {
if (trackPad) {
@@ -944,7 +962,6 @@ public class StaticLayout extends Layout {
}
}
-
if (needMultiply && !lastLine) {
double ex = (below - above) * (spacingmult - 1) + spacingadd;
if (ex >= 0) {
@@ -960,6 +977,15 @@ public class StaticLayout extends Layout {
lines[off + TOP] = v;
lines[off + DESCENT] = below + extra;
+ // special case for non-ellipsized last visible line when maxLines is set
+ // store the height as if it was ellipsized
+ if (!mEllipsized && currentLineIsTheLastVisibleOne) {
+ // below calculation as if it was the last line
+ int maxLineBelow = includePad ? bottom : below;
+ // similar to the calculation of v below, without the extra.
+ mMaxLineHeight = v + (maxLineBelow - above);
+ }
+
v += (below - above) + extra;
lines[off + mColumns + START] = end;
lines[off + mColumns + TOP] = v;
@@ -981,23 +1007,6 @@ public class StaticLayout extends Layout {
start - widthStart, end - start);
}
- if (ellipsize != null) {
- // If there is only one line, then do any type of ellipsis except when it is MARQUEE
- // if there are multiple lines, just allow END ellipsis on the last line
- boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount);
-
- boolean doEllipsis =
- (((mMaximumVisibleLineCount == 1 && moreChars) || (firstLine && !moreChars)) &&
- ellipsize != TextUtils.TruncateAt.MARQUEE) ||
- (!firstLine && (currentLineIsTheLastVisibleOne || !moreChars) &&
- ellipsize == TextUtils.TruncateAt.END);
- if (doEllipsis) {
- calculateEllipsis(start, end, widths, widthStart,
- ellipsisWidth, ellipsize, j,
- textWidth, paint, forceEllipsis);
- }
- }
-
mLineCount++;
return v;
}
@@ -1105,7 +1114,7 @@ public class StaticLayout extends Layout {
}
}
}
-
+ mEllipsized = true;
mLines[mColumns * line + ELLIPSIS_START] = ellipsisStart;
mLines[mColumns * line + ELLIPSIS_COUNT] = ellipsisCount;
}
@@ -1243,6 +1252,25 @@ public class StaticLayout extends Layout {
return mEllipsizedWidth;
}
+ /**
+ * Return the total height of this layout.
+ *
+ * @param cap if true and max lines is set, returns the height of the layout at the max lines.
+ *
+ * @hide
+ */
+ public int getHeight(boolean cap) {
+ if (cap && mLineCount >= mMaximumVisibleLineCount && mMaxLineHeight == -1 &&
+ Log.isLoggable(TAG, Log.WARN)) {
+ Log.w(TAG, "maxLineHeight should not be -1. "
+ + " maxLines:" + mMaximumVisibleLineCount
+ + " lineCount:" + mLineCount);
+ }
+
+ return cap && mLineCount >= mMaximumVisibleLineCount && mMaxLineHeight != -1 ?
+ mMaxLineHeight : super.getHeight();
+ }
+
private static native long nNewBuilder();
private static native void nFreeBuilder(long nativePtr);
private static native void nFinishBuilder(long nativePtr);
@@ -1281,6 +1309,21 @@ public class StaticLayout extends Layout {
private int mColumns;
private int mEllipsizedWidth;
+ /**
+ * Keeps track if ellipsize is applied to the text.
+ */
+ private boolean mEllipsized;
+
+ /**
+ * If maxLines is set, ellipsize is not set, and the actual line count of text is greater than
+ * or equal to maxLine, this variable holds the ideal visual height of the maxLine'th line
+ * starting from the top of the layout. If maxLines is not set its value will be -1.
+ *
+ * The value is the same as getLineTop(maxLines) for ellipsized version where structurally no
+ * more than maxLines is contained.
+ */
+ private int mMaxLineHeight = -1;
+
private static final int COLUMNS_NORMAL = 4;
private static final int COLUMNS_ELLIPSIZE = 6;
private static final int START = 0;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9c48cf8e8806..73af7558100f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5157,7 +5157,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* call {@link InputMethodManager#restartInput(View)}.</p>
* @param hintLocales List of the languages that the user is supposed to switch to no matter
* what input method subtype is currently used. Set {@code null} to clear the current "hint".
- * @see #getImeHIntLocales()
+ * @see #getImeHintLocales()
* @see android.view.inputmethod.EditorInfo#hintLocales
*/
public void setImeHintLocales(@Nullable LocaleList hintLocales) {
@@ -7000,11 +7000,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
.setLineSpacing(mSpacingAdd, mSpacingMult)
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
- .setHyphenationFrequency(mHyphenationFrequency);
+ .setHyphenationFrequency(mHyphenationFrequency)
+ .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
if (shouldEllipsize) {
builder.setEllipsize(mEllipsize)
- .setEllipsizedWidth(ellipsisWidth)
- .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ .setEllipsizedWidth(ellipsisWidth);
}
mHintLayout = builder.build();
}
@@ -7091,11 +7091,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
.setLineSpacing(mSpacingAdd, mSpacingMult)
.setIncludePad(mIncludePad)
.setBreakStrategy(mBreakStrategy)
- .setHyphenationFrequency(mHyphenationFrequency);
+ .setHyphenationFrequency(mHyphenationFrequency)
+ .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
if (shouldEllipsize) {
builder.setEllipsize(effectiveEllipsize)
- .setEllipsizedWidth(ellipsisWidth)
- .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+ .setEllipsizedWidth(ellipsisWidth);
}
// TODO: explore always setting maxLines
result = builder.build();
@@ -7367,9 +7367,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return 0;
}
- int linecount = layout.getLineCount();
- int pad = getCompoundPaddingTop() + getCompoundPaddingBottom();
- int desired = layout.getLineTop(linecount);
+ /*
+ * Don't cap the hint to a certain number of lines.
+ * (Do cap it, though, if we have a maximum pixel height.)
+ */
+ int desired = layout.getHeight(cap);
final Drawables dr = mDrawables;
if (dr != null) {
@@ -7377,31 +7379,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
desired = Math.max(desired, dr.mDrawableHeightRight);
}
- desired += pad;
-
- if (mMaxMode == LINES) {
- /*
- * Don't cap the hint to a certain number of lines.
- * (Do cap it, though, if we have a maximum pixel height.)
- */
- if (cap) {
- if (linecount > mMaximum) {
- desired = layout.getLineTop(mMaximum);
+ desired += getCompoundPaddingTop() + getCompoundPaddingBottom();
- if (dr != null) {
- desired = Math.max(desired, dr.mDrawableHeightLeft);
- desired = Math.max(desired, dr.mDrawableHeightRight);
- }
-
- desired += pad;
- linecount = mMaximum;
- }
- }
- } else {
+ if (mMaxMode != LINES) {
desired = Math.min(desired, mMaximum);
}
if (mMinMode == LINES) {
+ int linecount = layout.getLineCount();
if (linecount < mMinimum) {
desired += getLineHeight() * (mMinimum - linecount);
}