24

I have a scrollview containing a textview in an Android app. This textview will have text appended to it continuously at set intervals. Scrolling works and the text adds just fine, but what I'd like to do is have the scrollview autoscroll down as text is added. As new text is appended at the bottom, it automatically scrolls down to match and old text is pushed out of sight at the top. What would be even better is to add text to the bottom of the scrollview and have it push older text upward, but one thing at a time.

AndroidHopeful
  • 269
  • 1
  • 2
  • 4
  • 2
    Well...disregard that. Silly me not setting the gravity to "bottom" on the textview (not the scrollview) in the first place. Doing so keeps the new text at the bottom and scrolls to meet the new text. Yay! – AndroidHopeful Mar 07 '11 at 20:32
  • 3
    you can write about your solution in an answer and then mark it as selected. That way when other people encounter the same problem, they will see that there is a solution. – Shade Mar 08 '11 at 00:10
  • 2
    that is a cool solution and you should post it as an answer. – dylan murphy Jun 09 '11 at 13:50

5 Answers5

18
<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:fillViewport="true"
    >
    <TextView
        android:id="@+id/statusText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom" />
</ScrollView>
papaiatis
  • 4,231
  • 4
  • 26
  • 38
10

I've tried the solution with gravity but result was a lot of empty space under actual text when scroll to bottom.

So that is another way. You can place your TextView inside of ScrollView:

<ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:fillViewport="true" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</ScrollView>

And define addTextChangedListener

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

            //some code here

        ScrollView scrollView1 = (ScrollView) findViewById(R.id.scrollView1);
        TextView textView1 = (TextView) findViewById(R.id.textView1);
        textView1.addTextChangedListener(new TextWatcher() {

        @Override
        public void afterTextChanged(Editable arg0) {
            scrollView1.fullScroll(ScrollView.FOCUS_DOWN);
            // you can add a toast or whatever you want here
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1,
                int arg2, int arg3) {
            //override stub
        }

        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {
            //override stub
        }

    }) }

Actually i noticed right now that the application will scroll every time the text is changed, not just added. However it works just fine for me.

Kamarado
  • 391
  • 4
  • 5
  • This one is the only that works for me (API 23). The `android:layout_gravity="bottom"` trick was making me unable to scroll up manually and was adding plenty of empty space below the text. This one adds no empty space and allows scrolling normally. – Shlublu Nov 14 '16 at 16:15
3

You can simply scroll the whole ScrollView to the bottom when text is added.

textView.append(text);
scrollView.fullScroll(View.FOCUS_DOWN);

As @RaphaelRoyer-Rivard suggested in his comment, you can get more solid result with post:

textView.append(text);
scrollView.post(() -> scrollView.fullScroll(View.FOCUS_DOWN));
hata
  • 11,633
  • 6
  • 46
  • 69
dilix
  • 3,761
  • 3
  • 31
  • 55
0

If you're looking for a more generic way of auto-scrolling to the bottom of a ScrollView, you could try the snippet below. It has the advantage that you don't need to post a Runnable to make sure you're in the UI thread. It has the disadvantage that I'm not sure what things this could break.

public class AutoScroller extends ScrollView {
    public boolean autoscroll = true;

    public AutoScroller(Context context) {super(context);}
    public AutoScroller(Context context, AttributeSet attrs) {super(context,attrs);}
    public AutoScroller(Context context, AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr);}
    public AutoScroller(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if(autoscroll) {
           scrollTo(getScrollX(), getChildAt(getChildCount()-1).getBottom() - getHeight());
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

Another candidat to override might be onLayout.

kristianlm
  • 1,071
  • 1
  • 10
  • 14
-1
textView.append(text);
scroll.fullScroll(View.FOCUS_DOWN)

this will give problem, it won't scroll upto extreme top, due to android:layout_gravity="bottom"

Chaitanya K
  • 1,827
  • 4
  • 32
  • 67
sekhar
  • 7
  • 2