автоматическая прокрутка TextView в Android для отображения текста - PullRequest
46 голосов
/ 18 августа 2010

У меня есть TextView, к которому я динамически добавляю текст.

в моем файле main.xml У меня установлены свойства, чтобы сделать мои максимальные линии 19 и полосы прокрутки вертикальными.

в файле .java я использую textview.setMovementMethod(new ScrollingMovementMethod()); для прокрутки.

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

Я записываю значение для textview.getScrollY(), и оно остается на 0, несмотря ни на что (даже если я вручную прокручиваю его вниз и добавляюновая строка текста).

следовательно textview.scrollTo(0, textview.getScrollY()); ничего не делает для меня.

Есть ли другой метод, который я должен использовать для получения суммы вертикальной прокрутки для textview?Все, что я прочитал, говорит о том, что во всех отношениях все, что я делаю, должно работать: /

Ответы [ 12 ]

70 голосов
/ 08 сентября 2011

Немного покопался в источнике TextView, но вот что я придумал. Это не требует от вас оборачивать TextView в ScrollView и, насколько я могу судить, работает отлично.

// function to append a string to a TextView as a new line
// and scroll to the bottom if needed
private void addMessage(String msg) {
    // append the new string
    mTextView.append(msg + "\n");
    // find the amount we need to scroll.  This works by
    // asking the TextView's internal layout for the position
    // of the final line and then subtracting the TextView's height
    final int scrollAmount = mTextView.getLayout().getLineTop(mTextView.getLineCount()) - mTextView.getHeight();
    // if there is no need to scroll, scrollAmount will be <=0
    if (scrollAmount > 0)
        mTextView.scrollTo(0, scrollAmount);
    else
        mTextView.scrollTo(0, 0);
}

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

Редактировать: я должен упомянуть, что я также использую

mTextView.setMovementMethod(new ScrollingMovementMethod());

после создания экземпляра моего TextView.

53 голосов
/ 02 октября 2012

Используйте android:gravity="bottom" для TextView в макете XML.Например,

<TextView
    ...
    android:gravity="bottom"
    ...
/>

Не спрашивайте меня, почему это работает.

Единственная проблема этого метода заключается в том, что если вы хотите затем прокрутить назад текстовое представление, оно будет снова «опускаться» вниз при каждом добавлении нового текста.

28 голосов
/ 06 января 2011

это то, что я использую, чтобы прокрутить весь текст чата до конца ...

public void onCreate(Bundle savedInstanceState)
{
    this.chat_ScrollView = (ScrollView) this.findViewById(R.id.chat_ScrollView);
    this.chat_text_chat = (TextView) this.findViewById(R.id.chat_text_chat);
}


public void addTextToTextView()
{
    String strTemp = "TestlineOne\nTestlineTwo\n";

    //append the new text to the bottom of the TextView
    chat_text_chat.append(strTemp);

    //scroll chat all the way to the bottom of the text
    //HOWEVER, this won't scroll all the way down !!!
    //chat_ScrollView.fullScroll(View.FOCUS_DOWN);

    //INSTEAD, scroll all the way down with:
    chat_ScrollView.post(new Runnable()
    {
        public void run()
        {
            chat_ScrollView.fullScroll(View.FOCUS_DOWN);
        }
    });
}

РЕДАКТИРОВАТЬ: вот XML-макет

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <!-- center chat display -->
    <ScrollView android:id="@+id/chat_ScrollView"
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:layout_alignParentRight="true"
        android:layout_alignParentLeft="true">

        <TextView android:id="@+id/chat_text_chat"
            android:text="center chat" 
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent"
            android:singleLine="false" />

    </ScrollView>

</RelativeLayout>
21 голосов
/ 05 марта 2012

Предыдущие ответы у меня не работали правильно, однако это работает.

Создайте TextView и сделайте следующее:

// ...
mTextView = (TextView)findViewById(R.id.your_text_view);
mTextView.setMovementMethod(new ScrollingMovementMethod());
// ...

Используйте следующую функцию для добавления текста в TextView.

private void appendTextAndScroll(String text)
{
    if(mTextView != null){
        mTextView.append(text + "\n");
        final Layout layout = mTextView.getLayout();
        if(layout != null){
            int scrollDelta = layout.getLineBottom(mTextView.getLineCount() - 1) 
                - mTextView.getScrollY() - mTextView.getHeight();
            if(scrollDelta > 0)
                mTextView.scrollBy(0, scrollDelta);
        }
    }
}

Надеюсь, это поможет.

7 голосов
/ 08 апреля 2017

TextView уже имеет автоматическую прокрутку, если вы задаете текст, используя строки Spannable или Editable с установленной в них позицией курсора.

Сначала установите метод прокрутки:

mTextView.setMovementMethod(new ScrollingMovementMethod());

Затем используйте следующее для установки текста:

SpannableString spannable = new SpannableString(string);
Selection.setSelection(spannable, spannable.length());
mTextView.setText(spannable, TextView.BufferType.SPANNABLE);

setSelection () перемещает курсор к этому индексу. Когда TextView установлен на SPANNABLE, он автоматически прокручивается, чтобы сделать курсор видимым. Обратите внимание, что это не рисует курсор, он просто прокручивает местоположение курсора, чтобы быть в видимой части TextView.

Кроме того, поскольку TextView.append () обновляет текст до TextView.BufferType.EDITABLE и Editable реализует Spannable, вы можете сделать это:

mTextView.append(string);
Editable editable = mTextView.getEditableText();
Selection.setSelection(editable, editable.length());

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

import android.content.Context;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.MovementMethod;
import android.text.method.ScrollingMovementMethod;
import android.text.method.Touch;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityEvent;
import android.widget.TextView;

public class AutoScrollTextView extends AppCompatEditText {
    public AutoScrollTextView(Context context) {
        this(context, null);
    }

    public AutoScrollTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AutoScrollTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected boolean getDefaultEditable() {
        return false;
    }

    @Override
    protected MovementMethod getDefaultMovementMethod() {
        return new CursorScrollingMovementMethod();
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(text, type);
        scrollToEnd();
    }

    @Override
    public void append(CharSequence text, int start, int end) {
        super.append(text, start, end);
        scrollToEnd();
    }

    public void scrollToEnd() {
        Editable editable = getText();
        Selection.setSelection(editable, editable.length());
    }

    @Override
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(event);
        event.setClassName(AutoScrollTextView.class.getName());
    }

    /**
     * Moves cursor when scrolled so it doesn't auto-scroll on configuration changes.
     */
    private class CursorScrollingMovementMethod extends ScrollingMovementMethod {

        @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
            widget.moveCursorToVisibleOffset();
            return super.onTouchEvent(widget, buffer, event);
        }
    }
}
4 голосов
/ 15 ноября 2013
 scrollview=(ScrollView)findViewById(R.id.scrollview1); 
 tb2.setTextSize(30); 
 tb2=(TextView)findViewById(R.id.textView2);                 
 scrollview.fullScroll(View.FOCUS_DOWN);    

Или используйте это в TextView:

<TextView

android:id="@+id/tb2"
android:layout_width="fill_parent"
android:layout_height="225sp"
android:gravity="top"
android:background="@android:drawable/editbox_background"
android:scrollbars="vertical"/>
2 голосов
/ 12 октября 2017

(2017) с использованием Kotlin:

// you need this to enable scrolling:
mTextView.movementMethod = ScrollingMovementMethod()
// to enable horizontal scrolling, that means word wrapping off:
mTextView.setHorizontallyScrolling(true)
...
mTextView.text = "Some long long very long text content"
mTextView.post {
     val scrollAmount = mTextView.layout.getLineTop(mTextView.lineCount) - mTextView.height
     mTextView.scrollTo(0, scrollAmount)
}

Это работает файл для меня

2 голосов
/ 01 декабря 2014

Я использовал маленький трюк ... в моем случае ....

<FrameLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_below="@+id/textView"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_above="@+id/imageButton">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/scrollView"
        android:layout_gravity="left|top" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:inputType="textMultiLine"
            android:ems="10"
            android:text="@string/your_text" />
    </ScrollView>

</FrameLayout>
1 голос
/ 18 апреля 2016

Простая реализация ... в вашем XML-макете определите ваш TextView с этими атрибутами:

<TextView
    ...
    android:gravity="bottom"
    android:scrollbars="vertical"
/>
1 голос
/ 09 марта 2013
// Layout Views
    private TextView mConversationView;
    private ScrollView mConversationViewScroller;

use it either in :

public void onCreate(Bundle savedInstanceState)
{
   //...blabla
   setContentView(R.layout.main); 
   //...blablabla
        mConversationView = (TextView) findViewById(R.id.in);       
        mConversationViewScroller = (ScrollView) findViewById(R.id.scroller);
}

or in "special" method e.g. 

public void initializeChatOrSth(...){
        //...blabla
        mConversationView = (TextView) findViewById(R.id.in);       
        mConversationViewScroller = (ScrollView) findViewById(R.id.scroller);
}

public void addTextToTextView()
{

             //...blablabla some code
                byte[] writeBuf = (byte[]) msg.obj;
          // construct a string from the buffer - i needed this or You can use by"stringing"
                String writeMessage = new String(writeBuf);
                mConversationView.append("\n"+"Me:  " + writeMessage);
                mConversationViewScroller.post(new Runnable()
                {
                    public void run()
                    {
                        mConversationViewScroller.fullScroll(View.FOCUS_DOWN);
                    }
                });
}

this one works fine, also we can maually scroll text to the very top - which is impossible when gravity tag in XML is used.

Of course XML (main) the texview should be nested inside scrollview , e.g:

<ScrollView
        android:id="@+id/scroller"
        android:layout_width="match_parent"
        android:layout_height="280dp"
        android:fillViewport="true"
        android:keepScreenOn="true"
        android:scrollbarStyle="insideInset"
        android:scrollbars="vertical" >

        <TextView
            android:id="@+id/in"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:keepScreenOn="true"
            android:scrollbars="vertical" >

        </TextView>
    </ScrollView>
...