Как получить количество строк TextView?

Я хочу получить количество строк текстового вида

textView.setText("Test line 1 Test line 2 Test line 3 Test line 4 Test line 5.............") 

textView.getLineCount(); всегда возвращает ноль

Затем я также попробовал:

 ViewTreeObserver vto = this.textView.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { ViewTreeObserver obs = textView.getViewTreeObserver(); obs.removeGlobalOnLayoutListener(this); System.out.println(": " + textView.getLineCount()); } }); 

Он возвращает точный результат.

Но это работает только для статического макета.

Когда я раздуваю макет динамически, это больше не работает.

Как найти количество строк в TextView?

Я смог получить getLineCount() чтобы не возвращать 0 с помощью post , например:

 textview.setText(“Some text”); textview.post(new Runnable() { @Override public void run() { int lineCount = textview.getLineCount(); // Use lineCount here } }); 

Как упоминалось в этом сообщении ,

getLineCount() даст вам правильное количество строк только после прохода макета.

Это означает, что перед getLineCount() метода getLineCount() нужно сначала визуализировать TextView .

ViewTreeObserver не так надежен, особенно при использовании динамических макетов, таких как ListView.

Предположим: 1. Вы будете выполнять некоторую работу в зависимости от линий TextView. 2. Работа не очень срочна и может быть выполнена позже.

Вот мое решение:

 public class LayoutedTextView extends TextView { public LayoutedTextView(Context context) { super(context); } public LayoutedTextView(Context context, AttributeSet attrs) { super(context, attrs); } public LayoutedTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public interface OnLayoutListener { void onLayouted(TextView view); } private OnLayoutListener mOnLayoutListener; public void setOnLayoutListener(OnLayoutListener listener) { mOnLayoutListener = listener; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (mOnLayoutListener != null) { mOnLayoutListener.onLayouted(this); } } } 

Применение:

  LayoutedTextView tv = new LayoutedTextView(context); tv.setOnLayoutListener(new OnLayoutListener() { @Override public void onLayouted(TextView view) { int lineCount = view.getLineCount(); // do your work } }); 

Я думаю, что суть этого вопроса заключается в том, что люди хотят заранее узнать размер TextView, чтобы они могли динамически изменять его размер, чтобы хорошо подгонять текст. Типичным использованием может быть создание пузырьков разговоров (по крайней мере, это то, над чем я работал).

Я попробовал несколько решений, включая использование getTextBounds () и measureText (), как описано здесь . К сожалению, оба метода несколько неточны и не имеют возможности учитывать разрывы строк и неиспользуемые строки. Итак, я отказался от такого подхода.

Это оставляет getLineCount (), проблема которого заключается в том, что вы должны «визуализировать» текст до того, как getLineCount () предоставит вам количество строк, что делает его ситуацией с курицей и яйцом. Я читал различные решения с участием слушателей и макетов, но просто не мог поверить, что нет ничего проще.

Поймав два дня, я наконец нашел то, что искал (по крайней мере, это работает для меня). Все сводится к тому, что означает «визуализировать» текст. Это не означает, что текст должен появляться на экране, только чтобы он был подготовлен для отображения внутри. Это происходит всякий раз, когда вызов выполняется непосредственно для invalidate () или косвенно, как при использовании setText () в TextView, который вызывает invalidate () для вас, поскольку представление изменило внешний вид.

Во всяком случае, вот ключевой код (предположим, что вы уже знаете строку linewidth и lineHeight в текстовом пузыре одной строки на основе шрифта):

 TextView talkBubble; // No peeking while we set the bubble up. talkBubble.setVisibility( View.INVISIBLE ); // I use FrameLayouts so my talk bubbles can overlap // lineHeight is just a filler at this point talkBubble.setLayoutParams( new FrameLayout.LayoutParams( lineWidth, lineHeight ) ); // setText() calls invalidate(), which makes getLineCount() do the right thing. talkBubble.setText( "This is the string we want to dynamically deal with." ); int lineCount = getLineCount(); // Now we set the real size of the talkBubble. talkBubble.setLayoutParams( new FrameLayout.LayoutParams( lineWidth, lineCount * lineHeight ) ); talkBubble.setVisibility( View.VISIBLE ); 

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

Примечание. В реальной программе я использую отдельный пузырь для определения строк текста, чтобы я мог динамически изменять мой реальный пузырь как по длине, так и по ширине. Это позволяет мне сжимать мои пузыри слева направо для коротких инструкций и т. Д.

Наслаждайтесь!

Основываясь на идее @secnelis , есть даже более чистый способ, если вы нацеливаете API 11 или выше.

Вместо расширения TextView вы можете использовать уже встроенную функциональность, если View.OnLayoutChangeListener

В ListAdapter.getView() , например

 if (h.mTitle.getLineCount() == 0 && h.mTitle.getText().length() != 0) { h.mTitle.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(final View v, final int left, final int top, final int right, final int bottom, final int oldLeft, final int oldTop, final int oldRight, final int oldBottom) { h.mTitle.removeOnLayoutChangeListener(this); final int count = h.mTitle.getLineCount(); // do stuff } }); } else { final int count = h.mTitle.getLineCount(); // do stuff } 
  holder.tv_prayerDesc.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { try { final int lineCount = holder.tv_prayerDesc.getLayout().getLineCount(); Log.e("linecount",lineCount+""); if(lineCount<=5) { holder.show.setVisibility(View.GONE); } }catch (Exception e) { e.printStackTrace(); } return true; } }); 

Вы делаете это onCreate ? Представления еще не выложены, поэтому getLineCount() равно 0. Если вы сделаете это позже в окне LifeCycle, вы получите количество строк. У вас будет onCreate сделать это onCreate , но onWindowFocusChanged с hasFocus=true обычно имеет измерения, измеренные до сих пор.

Предложение textView.post() также является хорошим

Давайте будем гением компьютера.