如何判断我的textview是否已被椭圆化?


77

我有一个多行TextViewandroid:ellipsize="end"设定。但是,我想知道我放置的字符串是否太长(这样我可以确保完整的字符串显示在页面的其他位置)。

我可以使用TextView.length()并找到大约适合的字符串长度,但是由于它是多行,所以可以TextView处理何时换行,因此这并不总是可行。

有任何想法吗?

Answers:


122

您可以获取的布局,TextView并检查每行的省略号计数。对于省略号,只需检查最后一行即可,如下所示:

Layout l = textview.getLayout();
if (l != null) {
    int lines = l.getLineCount();
    if (lines > 0)
        if (l.getEllipsisCount(lines-1) > 0)
            Log.d(TAG, "Text is ellipsized");
}

这仅在布局阶段之后才起作用,否则返回的布局将为null,因此请在代码中的适当位置调用它。


7
如果您在输入的最后一行输入没有空格的长文本,例如“ jashdkjashdkjashdkasjhdashdkasjdhkajsdhkasjdhakjshdksjahdaksjhdajkshdkajshdkjashdkjashdkjashdja”,则失败。在这种情况下,getEllipsisCount()将返回0。要解决此问题,您不仅要检查最后一行,还必须遍历所有行并检查(l.getEllipsisCount(n)> 0)是否返回true;对于所有0 <= n <行。
Tiago 2015年

1
由于getEllipsisCountAPI <= 14中的函数错误,如果文本包含特殊字符(如\ n),它将失败并返回0。因此,可以通过使用支持库并替换if (l.getEllipsisCount(lines-1) > 0)为来解决此问题if (l.getEllipsisCount(lines-1) > 0 || TextViewCompat.getMaxLines(this))
巴姆(Bam)

1
gh,

@ r3flssExlUtr,这就是为什么呢?
zarsky

您能否详细说明布局阶段的含义。您是说版式膨胀时为什么?为什么以后会变为null?
6rchid

34

textView.getLayout是一种解决方法,但是存在的问题是,如果未准备好布局,它将返回null。使用以下解决方案。

 ViewTreeObserver vto = textview.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
           Layout l = textview.getLayout();
           if ( l != null){
              int lines = l.getLineCount();
              if ( lines > 0)
                  if ( l.getEllipsisCount(lines-1) > 0)
                    Log.d(TAG, "Text is ellipsized");
           }  
        }
    });

用于删除侦听器()的代码段:

mLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    public void onGlobalLayout() {
        scrollToGridPos(getCenterPoint(), false);
        mLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);        
    }
});

16
removeOnGlobalLayoutListener()当您不再需要它时,请不要忘记。
mmathieum 2013年

1
找到椭圆大小时添加此代码:if(Build.VERSION.SDK_INT <16){textview.getViewTreeObserver()。removeGlobalOnLayoutListener(this); } else {textview.getViewTreeObserver()。removeOnGlobalLayoutListener(this); }
丹尼尔·威尔逊

17
使用view.post()而不是VTO!这要简单得多。
一个人

更糟糕了,即使对于单行语句ifs
也要

1.使用In In Kotlin类型时,给定的错误分类器布局没有伴侣对象。2.函数返回0。请帮助我LayoutgetEllipsisCount
NIKUNJ GADHIYA

31

我认为这个问题最简单的解决方案是以下代码:

String text = "some looooong text";
textView.setText(text);
boolean isEllipsize = !((textView.getLayout().getText().toString()).equalsIgnoreCase(text));

此代码假定在您的XML中,TextView设置了maxLineCount:)


3
懒惰但有效:-D
msamardzic '16

4
如果设置了任何大写形式,则测试将失败。将toLowerCase()调用添加到两个字符串。
Yarh

1
如果您的textView.getLayout()返回null,则应使用:final ViewTreeObserver vto = tv.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){@Override public void onGlobalLayout(){tv.getViewTreeObserver()。removeOnGlobalLayoutListener(this); Layout layout = tv.getLayout(); if(!((layout.getText()。 toString())。equalsIgnoreCase(text))){//椭圆形} else {//非椭圆形}}}));
罗伊斯

3
在textView呈现文本之后需要执行此操作。textView.post(()-> {//在这里做})
Sarith NOB,

奇怪的是,两个对象的长度相同,但它们与可见对象却不同。
苏菲安

6

这对我有用:

textView.post(new Runnable() {
                        @Override
                        public void run() {
                            if (textView.getLineCount() > 1) {
                                //do something
                            }
                        }
                    });

节省了我的一天,因为ViewTreeObserver在RecyclerView中无法正常运行
吉勒·埃勒

4

public int getEllipsisCount(int行)

返回要省略的字符数,如果没有省略号,则返回0。

因此,只需致电:

int lineCount = textview1.getLineCount();

if(textview1.getLayout().getEllipsisCount(lineCount) > 0) {
   // Do anything here..
}

由于无法在设置布局之前调用getLayout(),因此请使用以下命令:

ViewTreeObserver vto = textview.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
       Layout l = textview.getLayout();
       if ( l != null){
          int lines = l.getLineCount();
          if ( lines > 0)
              if ( l.getEllipsisCount(lines-1) > 0)
                Log.d(TAG, "Text is ellipsized");
       }  
    }
});

最后,不要忘了在不再需要它时删除removeOnGlobalLayoutListener


您可以自由选择正确的答案。@FrancescoDonzello
amalBit 2014年

可能代码不是很出色,但是可以肯定的是。这解决了我确定文本是否已省略的问题。当您确实通过窗口管理器向窗口中添加视图时,此方法非常有用。
Yoraco Gonzales

可悲的是,如果省略号正好出现在空行(“ \ n”)中,那么它也将返回0,这是正确的,因为它发生在0索引字符中。因此,在那种情况下,这似乎并不是一种告诉...
Shyri

3
lateinit var toggleMoreButton: Runnable
toggleMoreButton = Runnable {
  if(reviewTextView.layout == null) { // wait while layout become available
       reviewTextView.post(toggleMoreButton) 
       return@Runnable
  }
  readMoreButton.visibility = if(reviewTextView.layout.text.toString() != comment) View.VISIBLE else View.GONE
}
reviewTextView.post(toggleMoreButton)

这是一些典型的情况:

  1. 在“ reviewTextView”中评论
  2. 评论可以按某些条件折叠
  3. 如果评论折叠,则显示按钮'readMoreButton'

简短的代码文本解释可能会使此答案更有用
charleslparker 18/12/22

我必须说这是简短的精确性,它是用kotlin写的。
雷库德

3

Kotlin方式:

textView.post {
   if (textView.lineCount > MAX_LINES_COLLAPSED) {
   // text is not fully displayed
   }
}

实际上View.post()是在渲染视图之后执行的,并将运行提供的功能


1

它为我工作

if (l != null) {
    int lines = l.getLineCount();
     if (lines > 0) {
     for (int i = 0; i < lines; i++) {
     if (l.getEllipsisCount(i) > 0) {
      ellipsize = true;
      break;
     }
    }
   }
  }

1

简单的Kotlin方法。允许android:ellipsizeandroid:maxLines被使用

fun isEllipsized(textView: TextView, text: String?) = textView.layout.text.toString() != text

您好,我了解您已将其转换为kotlin,但似乎已经有一个答案与您在Java中所做的完全相同。下次,您可以编辑现有答案,也可以在评论中建议对答案进行编辑,而不必添加全新的答案。快乐编码!
sep_im_batman

0

确实可以这样工作,例如,将完整的数据从RecyclerView的项目传递到对话框:

holder.subInfo.post(new Runnable() {
                @Override
                public void run() {
                    Layout l = holder.subInfo.getLayout();
                    if (l != null) {
                        final int count = l.getLineCount();
                        if (count >= 3) {
                            holder.subInfo.setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    final int c = holder.subInfo.getLineCount();
                                    if (c >= 3) {
                                        onClickToShowInfoDialog.showDialog(holder.title.getText().toString(), holder.subInfo.getText().toString());
                                    }
                                }
                            });
                        }
                    }
                }
            });

0

将@Thorstenvv遮篷与@Tiano修复结合使用,这是Kotlin版本:

val layout = textView.layout ?: return@doOnLayout
val lines = layout.lineCount
val hasLine = lines > 0
val hasEllipsis = ((lines - 1) downTo 0).any { layout.getEllipsisCount(it) > 0 }
if (hasLine && hasEllipsis) {
    // Text is ellipsized
}

0

Kotlin中,您可以使用以下代码。

var str= "Kotlin is one of the best languages."
textView.text=str
textView.post {
val isEllipsize: Boolean = !textView.layout.text.toString().equals(str)

if (isEllipsize) {
     holder.itemView.tv_viewMore.visibility = View.VISIBLE
} else {
     holder.itemView.tv_viewMore.visibility = View.GONE
}    
}

-1

使用getEllipsisCount不适用于其中包含空行的文本。我使用以下代码使其工作:

message.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {

            if(m.isEllipsized == -1) {
                Layout l = message.getLayout();
                if (message.getLineCount() > 5) {
                    m.isEllipsized = 1;
                    message.setMaxLines(5);
                    return false;
                } else {
                    m.isEllipsized = 0;
                }
            }
            return true;
        }
    });

确保不要maxLineCount在XML中设置A。然后,您可以lineCount在代码中检查,如果它大于某个数字,则可以返回false来取消绘制TextView并设置行数以及一个标志以保存文本视图是否太长。文本视图将以正确的行数再次绘制,并且您将知道是否带有标记将其椭圆化。

然后,您可以使用该isEllipsized标志执行所需的任何操作。


-1

TextViewUtils类中创建一个方法

public static boolean isEllipsized(String newValue, String oldValue) {
    return !((newValue).equals(oldValue));
}

需要时调用此方法,例如:

        if (TextViewUtils.isEllipsized(textviewDescription.getLayout().getText().toString(), yourModelObject.getDescription()))
            holder.viewMore.setVisibility(View.VISIBLE);//show view more option
        else
            holder.viewMore.setVisibility(View.GONE);//hide 

但是textView.getLayout()不能在设置view(layout)之前调用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.