在TextView中椭圆化SpannableString的各个行

时间:2013-04-03 22:00:34

标签: android textview ellipsis spannablestring

我有一个TextView存储一个两行长的地址。街道在第一行,并且是大胆的。城市与城市国家走在第二行,并不是大胆的。如果该行上的单个文本运行,我希望每行的结尾都是椭圆形的。我正在使用SpannableString来存储地址,因为我希望街道地址是大胆的,而城市和地址是国家不大胆。

如果没有为每一行使用两个TextViews,有没有办法做到这一点并不是完全黑客?

示例输出:

例如:
123812华盛顿A ...
Schenectady New Yor ......

例如:
2792 Dantzler Boulev ...
查尔斯顿SC,29406

例如:
3主街道 亚特兰大GA

3 个答案:

答案 0 :(得分:17)

我遇到了同样的问题,并通过创建EllipsizeLineSpan类来解决它。你可以用它包装你想要椭圆化的每一行。

使用它标记可跨越字符串的示例:

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

    }

}


}

答案 1 :(得分:1)

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

答案 2 :(得分:-2)

尝试在布局中设置TextView椭圆尺寸,如:

 android:ellipsize="end"