auto-scrolling TextView in android to bring text into view
I have a TextView
that I'm dynamically adding text to.
in my main.xml
file I have the properties set to make my max lines 19 and scrollbars vertical.
in the .java
file I am using textview.setMovementMethod(new ScrollingMovementMethod());
to allow for scrolling.
The scrolling works great. As soon as 19 lines are taken up, and more lines are added it starts scrolling just as it should. The problem is, I want the new text to scroll into view.
I am writing out the value for textview.getScrollY()
and it stays at 0
no matter what (even if I manually scroll it down and add a new line of text).
consequently textview.scrollTo(0, textview.getScrollY());
does nothing for me.
Is there another method I should be using to obtain the vertical scroll amount for the textview
? Everything I've read says that for all intents and purposes, what I'm doing should be working :/
Took some digging through the TextView source but here's what I came up with. It doesn't require you to wrap the TextView in a ScrollView and, as far as I can tell, works perfectly.
// 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);
}
Please let me know if you find a case where this fails. I'd appreciate being able to fix any bugs in my app ;)
Edit: I should mention that I also use
mTextView.setMovementMethod(new ScrollingMovementMethod());
after instantiating my TextView.
Use android:gravity="bottom"
on the TextView in your XML layout. E.g.
<TextView
...
android:gravity="bottom"
...
/>
Don't ask me why it works.
The only problem with this method is if you want to then scroll back up the textview, it keeps getting "pulled down" to the bottom again each time new text is inserted.
this is what I use to scroll all the way to the bottom of my chat text ...
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: here's the XML layout
<?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>
Previous answers did not work correctly for me, this however works.
Create a TextView and do the following:
// ...
mTextView = (TextView)findViewById(R.id.your_text_view);
mTextView.setMovementMethod(new ScrollingMovementMethod());
// ...
Use the following function to append text to the 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);
}
}
}
Hope this helps.