2013-04-03 2 views
4

У меня есть TextView, хранящий адрес длиной в две строки. Улица идет по первой линии и держится. Город & государство переходит на вторую строчку и не выделяется жирным шрифтом. Я хочу, чтобы конец каждой линии был эллипсирован, если отдельный текст на этой строке пробегает. Я использую SpannableString для хранения адреса, потому что хочу, чтобы адрес улицы был выделен жирным шрифтом, а город & не должен быть выделен полужирным шрифтом.Эллипсируйте отдельные строки SpannableString в TextView

Есть ли способ сделать это, что не является полным взломом без использования двух TextViews для каждой строки?

Пример выхода:

Ex:
123812 Washington A ...
Скенектади.Особенности Новый ёр ...

Ex:
2792 Dantzler Boulev ...
Charleston SC, 29406

Ex:
3 Главная улица
Atlanta GA

ответ

-1

Попробуйте установить размер TextView эллипс в макете, как:

android:ellipsize="end" 
+0

, но это будет просто эллипсизировать конец всего текста. Я хочу, чтобы обе линии были эллипсированы. – erin

+2

@erin Я не думаю, что это возможно с помощью одного «TextView», помещенного в несколько 'TextView', это трюк. – NullPointer

13

У меня была такая же проблема, и решить ее путем создания класса EllipsizeLineSpan. Вы можете обернуть каждую строку, которую вы хотите эллипсизировать.

Пример разметке spannable строку с ним:

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); 

    } 

} 


} 
0

ответ DangVarmit помог мне много, но после использования его на некоторое время, я обнаружил, что иногда Верхнее смещение текста случайным образом неверно. Вот часть, которую необходимо заменить:

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)) 
} 
Смежные вопросы