Skip to content

Commit 98dafda

Browse files
committed
use StaticLayout to correctly calculate text position
1 parent 28b6a13 commit 98dafda

File tree

1 file changed

+17
-21
lines changed

1 file changed

+17
-21
lines changed

android/src/main/java/com/expensify/livemarkdown/spans/MarkdownBackgroundSpan.java

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import android.graphics.Paint;
55
import android.graphics.Path;
66
import android.graphics.RectF;
7-
import android.text.Spanned;
8-
import android.text.style.LeadingMarginSpan;
7+
import android.text.StaticLayout;
8+
import android.text.TextPaint;
99
import android.text.style.LineBackgroundSpan;
1010

1111
import androidx.annotation.ColorInt;
@@ -18,11 +18,15 @@ public class MarkdownBackgroundSpan implements MarkdownSpan, LineBackgroundSpan
1818
private final int mentionEnd;
1919
private final float borderRadius;
2020

21+
private StaticLayout layout;
22+
private Path backgroundPath;
23+
2124
public MarkdownBackgroundSpan(@ColorInt int backgroundColor, float borderRadius, int mentionStart, int mentionEnd) {
2225
this.backgroundColor = backgroundColor;
2326
this.borderRadius = borderRadius;
2427
this.mentionStart = mentionStart;
2528
this.mentionEnd = mentionEnd;
29+
this.backgroundPath = new Path();
2630
}
2731

2832
@Override
@@ -39,36 +43,28 @@ public void drawBackground(
3943
int end,
4044
int lnum
4145
) {
42-
int leadingMargin = getLeadingMargin(text, start, end);
46+
if (layout == null || layout.getText() != text || layout.getWidth() != right || layout.getLineEnd(0) != end) {
47+
layout = StaticLayout.Builder.obtain(text, start, end, (TextPaint) paint, right).build();
48+
49+
boolean mentionStarts = start <= mentionStart;
50+
boolean mentionEnds = end >= mentionEnd;
4351

44-
boolean mentionStarts = start <= mentionStart;
45-
boolean mentionEnds = end >= mentionEnd;
52+
float startX = layout.getPrimaryHorizontal(mentionStarts ? mentionStart : start);
53+
float endX = layout.getPrimaryHorizontal(mentionEnds ? mentionEnd : end);
4654

47-
float startX = leadingMargin + (mentionStarts ? paint.measureText(text, start, mentionStart) : 0);
48-
float endX = leadingMargin + paint.measureText(text, start, mentionEnds ? mentionEnd : end);
55+
RectF lineRect = new RectF(startX, top, endX, bottom);
56+
backgroundPath.reset();
57+
backgroundPath.addRoundRect(lineRect, createRadii(mentionStarts, mentionEnds), Path.Direction.CW);
58+
}
4959

5060
int originalColor = paint.getColor();
5161
paint.setColor(backgroundColor);
5262

53-
RectF lineRect = new RectF(startX, top, endX, bottom);
54-
Path backgroundPath = new Path();
55-
backgroundPath.addRoundRect(lineRect, createRadii(mentionStarts, mentionEnds), Path.Direction.CW);
5663
canvas.drawPath(backgroundPath, paint);
5764

5865
paint.setColor(originalColor);
5966
}
6067

61-
private int getLeadingMargin(@NonNull CharSequence text, int start, int end) {
62-
int leadingMargin = 0;
63-
if (text instanceof Spanned spanned) {
64-
LeadingMarginSpan[] marginSpans = spanned.getSpans(start, end, LeadingMarginSpan.class);
65-
for (LeadingMarginSpan marginSpan : marginSpans) {
66-
leadingMargin += marginSpan.getLeadingMargin(true);
67-
}
68-
}
69-
return leadingMargin;
70-
}
71-
7268
private float[] createRadii(boolean roundedLeft, boolean roundedRight) {
7369
float[] radii = new float[8];
7470

0 commit comments

Comments
 (0)