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

如何在Android TextView中使用自定义省略号,android,textview,ellipsis,Android,Textview,Ellipsis,我有一个maxlines=3的TextView,我想使用我自己的省略号,而不是 "Lore ipsum ..." 我需要 "Lore ipsum ... [See more]" 为了给用户一个提示,点击视图将展开全文 可能吗 我正在考虑检查TextView是否有省略号,在这种情况下,添加文本“[查看更多]”,然后在前面设置省略号,但我找不到这样做的方法 也许如果我找到了文本被剪切的位置,我可以禁用省略号并生成一个子字符串,然后添加“…[查看更多]”,但我仍然不知道如何获得该位置。我最终以这种

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

"Lore ipsum ..."
我需要

"Lore ipsum ... [See more]"
为了给用户一个提示,点击视图将展开全文

可能吗

我正在考虑检查TextView是否有省略号,在这种情况下,添加文本“[查看更多]”,然后在前面设置省略号,但我找不到这样做的方法


也许如果我找到了文本被剪切的位置,我可以禁用省略号并生成一个子字符串,然后添加“…[查看更多]”,但我仍然不知道如何获得该位置。

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


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

我最初在这里发布了我的答案:


这里是到repo的链接:

@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;
            }
        });` 
ViewTreeObserver vto=previewContent.getViewTreeObserver();
addOnPreDrawListener(新的ViewTreeObserver.OnPreDrawListener(){
@凌驾
公共布尔onPreDraw(){
试一试{
Layout Layout=previewContent.getLayout();
int index1=layout.getLineStart(previewContent.getMaxLines());
if(index1>10&&index1
这里有一个使用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)
        }
    })
}
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
}
TextUtil.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)
        }
    })
}
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,“…请参阅更多”)


注意:如果文本来自服务器,并且可能有新行字符,则可以使用此方法确定文本是否已省略

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
来自
实现“org.apache.commons:commons-lang3:3.4”

以下是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)
    }
  }

请参阅
l.getEllipsisStart()
而不是像
ellipsis=“…”;
中那样使用三个点,您应该使用水平省略号字符(…;entity->
)textView.getLayout()返回null Android使用
TextUtils.省略号\u NORMAL[0]
用于标准省略号,解析为
'\u2026'
。这可以在TextView间接使用的方法中找到。已尝试在recyclerView.TextView.getLayout()中使用此方法返回null。是否需要进行任何修改以使其对回收器/列表视图有用?如果getLayout使用null,请使用ViewTreeObserver.OnGlobalLayoutListener.yup我在回收器视图中执行了此操作。这会降低整个性能,请确保将
yourTextView
替换为您试图省略的文本视图。是的,我正在执行此操作使用文本视图。但在handler@Xenolion我没有针对多行测试它,但我看不出它不起作用的任何原因。我想到的原因是布局。getEllipsisStart(line)为特定行提供省略号开头,但不是为所有文本提供省略号开头!可能是。我会说试试看。