Подтвердить что ты не робот

Как получить количество строк 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?

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

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

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

В любом случае, здесь key code (предположим, что вы уже знаете строку разговора в строке 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 );

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

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

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

Ответ 5

Основываясь на @secnelis idea, есть даже более чистый способ, если вы нацеливаете 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
}

Ответ 6

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

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

Ответ 7

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