如何在Android TextView中使用自定义省略号

时间:2014-09-26 07:57:19

标签: android textview ellipsis

我有一个maxlines = 3的TextView,我想使用自己的省略号,而不是

"Lore ipsum ..."

我需要

"Lore ipsum ... [See more]"

为了给用户一个线索,点击视图将扩展全文。

有可能吗?

我正在考虑检查TextView是否有省略号,在这种情况下添加文本" [查看更多]"之前就设定了省略号,但我找不到这样做的方法。

也许如果我找到文本被剪切的位置,我可以禁用省略号并创建子字符串,然后添加" ... [查看更多]",但我又不知道如何得到那个位置。

5 个答案:

答案 0 :(得分:6)

我终于以这种方式管理它(可能不是最好的):

private void setLabelAfterEllipsis(TextView textView, int labelId, int maxLines){

    if(textView.getLayout().getEllipsisCount(maxLines-1)==0) {
        return; // Nothing to do
    }

    int start = textView.getLayout().getLineStart(0);
    int end = textView.getLayout().getLineEnd(textView.getLineCount() - 1);
    String displayed = textView.getText().toString().substring(start, end);
    int displayedWidth = getTextWidth(displayed, textView.getTextSize());

    String strLabel = textView.getContext().getResources().getString(labelId);
    String ellipsis = "...";
    String suffix = ellipsis + strLabel;

    int textWidth;
    String newText = displayed;
    textWidth = getTextWidth(newText + suffix, textView.getTextSize());

    while(textWidth>displayedWidth){
        newText = newText.substring(0, newText.length()-1).trim();
        textWidth = getTextWidth(newText + suffix, textView.getTextSize());
    }

    textView.setText(newText + suffix);
}

private int getTextWidth(String text, float textSize){
    Rect bounds = new Rect();
    Paint paint = new Paint();
    paint.setTextSize(textSize);
    paint.getTextBounds(text, 0, text.length(), bounds);

    int width = (int) Math.ceil( bounds.width());
    return width;
}

答案 1 :(得分:1)

我认为@jmhostalet的答案会降低性能(尤其是在处理列表和大量TextView时),因为TextView会多次绘制文本。我创建了一个自定义TextView,可以在onMeasure()中解决此问题,因此只绘制一次文本。

我最初将答案发布在这里:https://stackoverflow.com/a/52589927/1680301

这是仓库的链接:https://github.com/TheCodeYard/EllipsizedTextView

答案 2 :(得分:0)

@George @jmhostalet我在回收者视图中这样做,这降低了整体性能。

ViewTreeObserver vto = previewContent.getViewTreeObserver();
    vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                try {
                    Layout layout = previewContent.getLayout();
                    int index1 = layout.getLineStart(previewContent.getMaxLines());
                    if (index1 > 10 && index1 < ab.getPreviewContent().length()) {
                        String s =
                                previewContent.getText().toString().substring(0, index1 - 10);
                        previewContent
                                .setText(Html.fromHtml(
                                        s + "<font color='#DC5530'>...और पढ़ें</font>"));
                    }
                    return true;
                }catch (Exception e)
                {
                    Crashlytics.logException(e);
                }
                return true;
            }
        });` 

答案 3 :(得分:0)

这是使用Kotlin扩展名的一种好方法。 请注意,在测量和附加后缀之前,我们需要等待视图布局。

TextViewExtensions.kt

fun TextView.setEllipsizedSuffix(maxLines: Int, suffix: String) {
    addOnLayoutChangeListener(object: View.OnLayoutChangeListener {
        override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom:     Int) {

            val allText = text.toString()
            var newText = allText
            val tvWidth = width
            val textSize = textSize

            if(!TextUtil.textHasEllipsized(newText, tvWidth, textSize, maxLines)) return

            while (TextUtil.textHasEllipsized(newText, tvWidth, textSize, maxLines)) {
                newText = newText.substring(0, newText.length - 1).trim()
            }

            //now replace the last few chars with the suffix if we can
            val endIndex = newText.length - suffix.length - 1 //minus 1 just to make sure we have enough room
            if(endIndex > 0) {
                newText = "${newText.substring(0, endIndex).trim()}$suffix"
            }

            text = newText

            removeOnLayoutChangeListener(this)
        }
    })
}

TextUtil.kt

fun textHasEllipsized(text: String, tvWidth: Int, textSize: Float, maxLines: Int): Boolean {
    val paint = Paint()
    paint.textSize = textSize
    val size = paint.measureText(text).toInt()

    return size > tvWidth * maxLines
}

然后实际上像这样使用它 myTextView.setEllipsizedSuffix(2, "...See more")


注意:如果您的文本来自服务器,并且可能包含换行符,则可以使用此方法确定文本是否为椭圆形。

fun textHasEllipsized(text: String, tvWidth: Int, textSize: Float, maxLines: Int): Boolean {
    val paint = Paint()
    paint.textSize = textSize
    val size = paint.measureText(text).toInt()
    val newLineChars = StringUtils.countMatches(text, "\n")

    return size > tvWidth * maxLines || newLineChars >= maxLines
}

StringUtils来自implementation 'org.apache.commons:commons-lang3:3.4'

答案 4 :(得分:0)

这是Kotlin的解决方案。

yourTextView.post {}是必需的,因为textview直到渲染后才会被椭圆化。

  val customSuffix = "... [See more]"
  yourTextView.post {
    if (yourTextView.layout.getEllipsisStart(-1) != -1) {
      val newText = yourTextView.text.removeRange(
          yourTextView.layout.getEllipsisStart(-1) - customSuffix.length, yourTextView.text.length
      )
      yourTextView.text = String.format("%s%s", newText, customSuffix)
    }
  }