Автоматическая прокрутка TextView в android для отображения текста

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

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

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

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

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

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

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

Solutions Collecting From Web of "Автоматическая прокрутка TextView в android для отображения текста"

Взял некоторый рыть через источник 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.

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

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

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

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

Это то, что я использую для прокрутки до конца моего текста чата …

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

EDIT: вот 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> 

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

Создайте 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); } } } 

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

  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"/> 

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

 <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> 
 // 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 eg 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 , eg: <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> 

Чтобы избежать создания фиктивного scroolview, я сделал

 int top_scr,rec_text_scrollY; top_scr=(int)rec_text.getTextSize()+rec_text.getHeight(); rec_text_scrollY=rec_text.getLineBounds(rec_text.getLineCount()-1, null)-top_scr; //repeat scroll here and in rec_text.post. //If not scroll here text will be "jump up" after new append, and immediately scroll down //If not scroll in post, than scroll will not be actually processed if(rec_text_scrollY>0)rec_text.scrollTo(0, rec_text_scrollY); rec_text.post(new Runnable(){ @Override public void run() { if(rec_text_scrollY>0)rec_text.scrollTo(0, rec_text_scrollY); } }); 

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

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

https://stackoverflow.com/a/7350267/4411645 не совсем сработало для меня

  1. GetLayout может вызывать NPE, когда текст был недавно изменен.
  2. ScrollTo следует изменить на scrollBy
  3. Он не учитывает относительное положение текста или прокладок.

Излишне говорить, что это хорошая отправная точка. Вот моя вариация реализации, внутри textwatcher. Мы должны вычесть верхнюю часть textView снизу при вычислении дельта, потому что getLineTop () также возвращает значение относительно вершины textView.

  @Override public void afterTextChanged(Editable editable) { new Handler().postDelayed(new Runnable() { @Override public void run() { Layout layout = textView.getLayout(); if (layout != null) { int lineTop = layout.getLineTop(textView.getLineCount()); final int scrollAmount = lineTop + textView.getPaddingTop() + textView.getPaddingBottom() - textView.getBottom() + textView.getTop(); if (scrollAmount > 0) { textView.scrollBy(0, scrollAmount); } else { textView.scrollTo(0, 0); } } } }, 1000L); } 

Вы можете поиграть с задержкой, чтобы улучшить ваш ux.

Вы можете добиться этого без scrollTo () без ScrollView без Runnable и без силы тяжести = "bottom", выполнив следующие действия:

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

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