Skip to content

Commit

Permalink
fix(android): fix premature text truncation
Browse files Browse the repository at this point in the history
  • Loading branch information
iPel committed Nov 24, 2023
1 parent bb9b7db commit 64accb7
Showing 1 changed file with 80 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ public void setLetterSpacing(float spacing) {
defaultNumber = Color.BLACK)
public void setColor(Integer color) {
mColor = color;
if (mTextPaintInstance != null) {
mTextPaintInstance.setColor(color);
}
markDirty();
}

Expand Down Expand Up @@ -408,43 +411,42 @@ protected void createSpanOperationImpl(@NonNull List<SpanOperation> ops,
int start = builder.length();
builder.append(getEmoticonText(text));
int end = builder.length();
if (start > end) {
return;
}
String verticalAlign = getVerticalAlign();
if (verticalAlign != null && !V_ALIGN_BASELINE.equals(verticalAlign)) {
TextVerticalAlignSpan span = new TextVerticalAlignSpan(verticalAlign);
ops.add(new SpanOperation(start, end, span, SpanOperation.PRIORITY_LOWEST));
}
ops.add(new SpanOperation(start, end, createForegroundColorSpan()));
if (mBackgroundColor != Color.TRANSPARENT && mParent != null) {
ops.add(new SpanOperation(start, end, new BackgroundColorSpan(mBackgroundColor)));
}
if (mLetterSpacing != 0) {
ops.add(new SpanOperation(start, end,
new TextLetterSpacingSpan(mLetterSpacing)));
}
int size = mFontSize;
if (mFontAdapter != null && mEnableScale) {
size = (int) (size * mFontAdapter.getFontScale());
}
ops.add(new SpanOperation(start, end, new AbsoluteSizeSpan(size)));
ops.add(new SpanOperation(start, end, new TextStyleSpan(mItalic, mFontWeight, mFontFamily, mFontAdapter)));
if (mHasUnderlineTextDecoration) {
ops.add(new SpanOperation(start, end, new UnderlineSpan()));
}
if (mHasLineThroughTextDecoration) {
ops.add(new SpanOperation(start, end, new StrikethroughSpan()));
}
if (mShadowOffsetDx != 0 || mShadowOffsetDy != 0) {
ops.add(new SpanOperation(start, end,
new TextShadowSpan(mShadowOffsetDx, mShadowOffsetDy, mShadowRadius,
mShadowColor)));
}
if (mEventTypes != null && mEventTypes.size() > 0) {
TextGestureSpan span = new TextGestureSpan(mId);
span.addGestureTypes(mEventTypes);
ops.add(new SpanOperation(start, end, span));
if (start < end) {
String verticalAlign = getVerticalAlign();
if (verticalAlign != null && !V_ALIGN_BASELINE.equals(verticalAlign)) {
TextVerticalAlignSpan span = new TextVerticalAlignSpan(verticalAlign);
ops.add(new SpanOperation(start, end, span, SpanOperation.PRIORITY_LOWEST));
}
ops.add(new SpanOperation(start, end, createForegroundColorSpan()));
if (mBackgroundColor != Color.TRANSPARENT && mParent != null) {
ops.add(new SpanOperation(start, end, new BackgroundColorSpan(mBackgroundColor)));
}
if (mLetterSpacing != 0) {
ops.add(new SpanOperation(start, end,
new TextLetterSpacingSpan(mLetterSpacing)));
}
int size = mFontSize;
if (mFontAdapter != null && mEnableScale) {
size = (int) (size * mFontAdapter.getFontScale());
}
ops.add(new SpanOperation(start, end, new AbsoluteSizeSpan(size)));
ops.add(new SpanOperation(start, end, new TextStyleSpan(mItalic, mFontWeight, mFontFamily, mFontAdapter)));
if (mHasUnderlineTextDecoration) {
ops.add(new SpanOperation(start, end, new UnderlineSpan()));
}
if (mHasLineThroughTextDecoration) {
ops.add(new SpanOperation(start, end, new StrikethroughSpan()));
}
if (mShadowOffsetDx != 0 || mShadowOffsetDy != 0) {
ops.add(new SpanOperation(start, end,
new TextShadowSpan(mShadowOffsetDx, mShadowOffsetDy, mShadowRadius,
mShadowColor)));
}
if (mEventTypes != null && mEventTypes.size() > 0) {
TextGestureSpan span = new TextGestureSpan(mId);
span.addGestureTypes(mEventTypes);
ops.add(new SpanOperation(start, end, span));
}
}
if (useChild) {
createChildrenSpanOperation(ops, builder);
Expand Down Expand Up @@ -528,7 +530,7 @@ protected Layout createLayout(final float width, final FlexMeasureMode widthMode
}

private TextPaint getTextPaint() {
if (TextUtils.isEmpty(mText)) {
if (TextUtils.isEmpty(mSpanned)) {
if (mTextPaintForEmpty == null) {
mTextPaintForEmpty = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
}
Expand All @@ -537,6 +539,7 @@ private TextPaint getTextPaint() {
if (mTextPaintInstance == null) {
mTextPaintInstance = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
mTextPaintInstance.setTextSize(mFontSize);
mTextPaintInstance.setColor(mColor);
}
return mTextPaintInstance;
}
Expand Down Expand Up @@ -615,21 +618,12 @@ private StaticLayout truncateLayoutWithNumberOfLine(Layout preLayout, int width,
}
CharSequence lastLine;
if (MODE_HEAD.equals(mEllipsizeMode)) {
float formerTextSize =
numberOfLines >= 2 ? getLineHeight(preLayout, numberOfLines - 2)
: paint.getTextSize();
float latterTextSize = Math.max(getLineHeight(preLayout, lineCount - 2),
getLineHeight(preLayout, lineCount - 1));
measurePaint.setTextSize(Math.max(formerTextSize, latterTextSize));
lastLine = ellipsizeHead(origin, measurePaint, width, start);
lastLine = ellipsizeHead(origin, measurePaint, width, preLayout.getLineStart(lineCount - 2));
} else if (MODE_MIDDLE.equals(mEllipsizeMode)) {
measurePaint.setTextSize(Math.max(getLineHeight(preLayout, numberOfLines - 1),
getLineHeight(preLayout, lineCount - 1)));
lastLine = ellipsizeMiddle(origin, measurePaint, width, start);
lastLine = ellipsizeMiddle(origin, measurePaint, width, start, preLayout.getLineEnd(numberOfLines),
preLayout.getLineStart(lineCount - 2));
} else /*if (MODE_TAIL.equals(mEllipsizeMode))*/ {
measurePaint.setTextSize(getLineHeight(preLayout, numberOfLines - 1));
int end = preLayout.getLineEnd(numberOfLines - 1);
lastLine = ellipsizeTail(origin, measurePaint, width, start, end);
lastLine = ellipsizeTail(origin, measurePaint, width, start, preLayout.getLineEnd(numberOfLines));
}
// concat everything
truncated = formerLines == null ? lastLine
Expand All @@ -641,12 +635,27 @@ private StaticLayout truncateLayoutWithNumberOfLine(Layout preLayout, int width,
return buildStaticLayout(truncated, paint, width);
}

private float getLineHeight(Layout layout, int line) {
return layout.getLineTop(line + 1) - layout.getLineTop(line);
private float chooseTextSize(float inherit, CharSequence text) {
float size = inherit;
if (text instanceof Spanned) {
AbsoluteSizeSpan[] spans = ((Spanned) text).getSpans(0, text.length(), AbsoluteSizeSpan.class);
if (spans != null && spans.length > 0) {
TextPaint tmp = new TextPaint();
tmp.setTextSize(size);
for (AbsoluteSizeSpan span : spans) {
span.updateMeasureState(tmp);
size = Math.max(size, tmp.getTextSize());
}
}
}
return size;
}

private CharSequence ellipsizeHead(CharSequence origin, TextPaint paint, int width, int start) {
start = Math.max(start, TextUtils.lastIndexOf(origin, '\n') + 1);
int index = TextUtils.lastIndexOf(origin, '\n', start, origin.length() - 1);
if (index != -1) {
start = index + 1;
}
// "…${last line of the rest part}"
CharSequence tmp;
if (origin instanceof Spanned) {
Expand All @@ -658,6 +667,7 @@ private CharSequence ellipsizeHead(CharSequence origin, TextPaint paint, int wid
.append(ELLIPSIS)
.append(origin, start, origin.length());
}
paint.setTextSize(chooseTextSize(paint.getTextSize(), tmp));
CharSequence result = TextUtils.ellipsize(tmp, paint, width, TextUtils.TruncateAt.START);
if (result instanceof Spannable) {
// make spans cover the "…"
Expand All @@ -677,11 +687,16 @@ private CharSequence ellipsizeHead(CharSequence origin, TextPaint paint, int wid
}

private CharSequence ellipsizeMiddle(CharSequence origin, TextPaint paint, int width,
int start) {
int leftEnd, rightStart;
if ((leftEnd = TextUtils.indexOf(origin, '\n', start)) != -1) {
rightStart = TextUtils.lastIndexOf(origin, '\n') + 1;
assert leftEnd < rightStart;
int start, int leftEnd, int rightStart) {
int index = TextUtils.indexOf(origin, '\n', start, leftEnd);
if (index != -1) {
leftEnd = index;
}
index = TextUtils.lastIndexOf(origin, '\n', rightStart, origin.length() - 1);
if (index != -1) {
rightStart = index + 1;
}
if (leftEnd < rightStart) {
// "${first line of the rest part}…${last line of the rest part}"
CharSequence tmp;
if (origin instanceof Spanned) {
Expand All @@ -704,6 +719,7 @@ public void ellipsized(int l, int r) {
outRange[1] = r;
}
};
paint.setTextSize(chooseTextSize(paint.getTextSize(), tmp));
CharSequence line = TextUtils.ellipsize(tmp, paint, width, TextUtils.TruncateAt.MIDDLE,
false, callback);
if (line != tmp) {
Expand All @@ -723,15 +739,16 @@ public void ellipsized(int l, int r) {
} else {
// "${only one line of the rest part}"
CharSequence tmp = origin.subSequence(start, origin.length());
paint.setTextSize(chooseTextSize(paint.getTextSize(), tmp));
return TextUtils.ellipsize(tmp, paint, width, TextUtils.TruncateAt.MIDDLE);
}
}

private CharSequence ellipsizeTail(CharSequence origin, TextPaint paint, int width, int start,
int end) {
if (origin.charAt(end - 1) == '\n') {
// there will be an unexpected blank line, if ends with a new line char, trim it
--end;
int index = TextUtils.indexOf(origin, '\n', start, end);
if (index != -1) {
end = index;
}
// "${first line of the rest part}…"
CharSequence tmp;
Expand All @@ -742,6 +759,7 @@ private CharSequence ellipsizeTail(CharSequence origin, TextPaint paint, int wid
tmp = new StringBuilder(end - start + ELLIPSIS.length())
.append(origin, start, end).append(ELLIPSIS);
}
paint.setTextSize(chooseTextSize(paint.getTextSize(), tmp));
return TextUtils.ellipsize(tmp, paint, width, TextUtils.TruncateAt.END);
}

Expand Down

0 comments on commit 64accb7

Please sign in to comment.