TextView already has auto-scrolling if you set the text using Spannable or Editable strings with the cursor position set in them.
First, set the scrolling method:
mTextView.setMovementMethod(new ScrollingMovementMethod());
Then use the following to set the text:
SpannableString spannable = new SpannableString(string);
Selection.setSelection(spannable, spannable.length());
mTextView.setText(spannable, TextView.BufferType.SPANNABLE);
The setSelection() moves the cursor to that index. When a TextView is set to a SPANNABLE it will automatically scroll to make the cursor visible. Note that this does not draw the cursor, it just scrolls the location of the cursor to be in the viewable section of the TextView.
Also, since TextView.append() upgrades the text to TextView.BufferType.EDITABLE and Editable implements Spannable, you can do this:
mTextView.append(string);
Editable editable = mTextView.getEditableText();
Selection.setSelection(editable, editable.length());
Here is a full widget implementation. Simply call setText() or append() on this widget. It's slightly different than above because it extends from EditText which already forces its internal text to be Editable.
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);
}
}
}