Ellipse individual SpannableString rows in a TextView

I have a TextView that stores a two-line address. The street is on the first line and keeps. The city and the state go along the second line and are not bold. I want the end of each line to be ellipse if a separate text on this line runs through. I use SpannableString to store the address, because I want the street address to be in bold and the city and state not to be in bold.

Is there a way to do this that is not a complete hack without using two TextViews for each row?

Output Example:

Example:
123812 Washington A ...
Schenectady New Yor ...

Example:
2792 Danzler Boolean ...
Charleston SC, 29406

Example:
3 Main street
Atlanta GA

+4
source share
3 answers

I had the same problem and decided to create an EllipsizeLineSpan class. You can wrap each line that you want to ellipse with it.

Example for marking with this line:

 SpannableStringBuilder textspan = new SpannableStringBuilder("#1.Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"+ "Protect from ellipsizing #2.Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"+ "#3.Lorem ipsum dolor sit amet, consectetur adipisicing elit\n"+ "#4.Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"); // find ellipsizable text (from '#' to newline) Pattern pattern = Pattern.compile("#.*\\n", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(textspan); while(matcher.find()) { textspan.setSpan(new EllipsizeLineSpan(), matcher.start(), matcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } 

EllipsizeLineSpan:

 public class EllipsizeLineSpan extends ReplacementSpan implements LineBackgroundSpan { int layoutLeft = 0; int layoutRight = 0; public EllipsizeLineSpan () { } @Override public void drawBackground (Canvas c, Paint p, int left, int right, int top, int baseline, int bottom, CharSequence text, int start, int end, int lnum) { Rect clipRect = new Rect(); c.getClipBounds(clipRect); layoutLeft = clipRect.left; layoutRight = clipRect.right; } @Override public int getSize (Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { return layoutRight - layoutLeft; } @Override public void draw (Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { float textWidth = paint.measureText(text, start, end); if (x + (int) Math.ceil(textWidth) < layoutRight) { //text fits canvas.drawText(text, start, end, x, y, paint); } else { float ellipsiswid = paint.measureText("\u2026"); // move 'end' to the ellipsis point end = start + paint.breakText(text, start, end, true, layoutRight - x - ellipsiswid, null); canvas.drawText(text, start, end, x, y, paint); canvas.drawText("\u2026", x + paint.measureText(text, start, end), y, paint); } } } 
+13
source

DangVarmit's answer helped me a lot, but after using it I found out that sometimes the top text offset is randomly wrong. Here is the part to be replaced:

  override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fontMetricsInt: Paint.FontMetricsInt?): Int { fontMetricsInt?.let { it.top = paint.getFontMetricsInt(it) } return Math.round(paint.measureText(text, start, start)) } 
0
source

Try setting the size of the TextView ellipse in your layout, for example:

  android:ellipsize="end" 
-1
source

Source: https://habr.com/ru/post/956956/


All Articles