Can I scroll a ScrollView programmatically in Android?
Asked Answered
E

19

161

Is there any way to scroll a ScrollView programmatically to a certain position?

I have created dynamic TableLayout which is placed in a ScrollView. So I want that on a specific action (like clicking a Button, etc.) the particular row should scroll automatically to a top position.

Is it possible?

Endowment answered 22/6, 2011 at 9:59 Comment(0)
O
175
ScrollView sv = (ScrollView)findViewById(R.id.scrl);
sv.scrollTo(0, sv.getBottom());

or

sv.scrollTo(5, 10);

Oxidase answered 22/6, 2011 at 10:16 Comment(3)
Combining ercu's answer and a comment made on it, the best way seems to be: mScrollView.post(new Runnable() { public void run() { mScrollView.fullScroll(View.FOCUS_DOWN); } });Sauternes
scrollTo() will not produce desire resull. One should go with fullScroll()Tetrastich
More nice scroll is with natural effect: sv.smoothScrollTo(5, 10)Furnary
W
214

The answer from Pragna does not work always, try this:

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.scrollTo(0, mScrollView.getBottom());
        } 
});

or

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_DOWN);
        } 
});

if You want to scroll to start

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_UP);
        } 
});
Wilen answered 30/12, 2011 at 22:26 Comment(11)
For me this scrolled it as far down as the length of the ScrollView appears on the screen, not to the very bottom (probably as I would expect).Godroon
I used mScrollView.fullScroll(mScrollView.FOCUS_DOWN); with success.Godroon
I can confirm Vanthel's findings. mScrollView.fullScroll in a post runnable did the trick.Nightly
Excellent ! Indeed, without the Runnable, it didn't work. Now, it works ! :)Madaras
For me without Runnable not work and when I use Runnable it's scroll but it's like choppy, not smooth and stable. can suggest why that happen ?Spasmodic
Much better answer than the one that is selected!Mayfair
@HiteshDhamshaniya If you want a smooth scroll, try mScrollView.smoothScrollTo(0, mScrollView.getBottom());.Nena
How has this received so many up-votes!? It's a hack, and the answer doesn't explain why it works. The selected answer (Pragna's) is sufficient. The question wasn't about trying to scroll prior to layout, it specifically mentioned in response to an event like a button press.Puce
@BenjaminDobell that's why the accepted answer is the accepted answer. But clearly it's pretty common to stumble across this answer when you're trying to do it before layout.Saltarello
Why it needs post here?Eponymy
It works for me when after hiding and showing some views there was some time lag and views were appearing twice on UI. Thanks. Works like Notifier when UI get changed inside ScrollViewKlagenfurt
O
175
ScrollView sv = (ScrollView)findViewById(R.id.scrl);
sv.scrollTo(0, sv.getBottom());

or

sv.scrollTo(5, 10);

Oxidase answered 22/6, 2011 at 10:16 Comment(3)
Combining ercu's answer and a comment made on it, the best way seems to be: mScrollView.post(new Runnable() { public void run() { mScrollView.fullScroll(View.FOCUS_DOWN); } });Sauternes
scrollTo() will not produce desire resull. One should go with fullScroll()Tetrastich
More nice scroll is with natural effect: sv.smoothScrollTo(5, 10)Furnary
I
36

I wanted the scrollView to scroll directly after onCreateView() (not after e.g. a button click). To get it to work I needed to use a ViewTreeObserver:

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });

But beware that this will be called everytime something gets layouted (e.g if you set a view invisible or similar) so don't forget to remove this listener if you don't need it anymore with:

public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) on SDK Lvl < 16

or

public void removeOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) in SDK Lvl >= 16

Isleana answered 15/5, 2013 at 9:43 Comment(0)
T
33

There are a lot of good answers here, but I only want to add one thing. It sometimes happens that you want to scroll your ScrollView to a specific view of the layout, instead of a full scroll to the top or the bottom.

A simple example: in a registration form, if the user tap the "Signup" button when a edit text of the form is not filled, you want to scroll to that specific edit text to tell the user that he must fill that field.

In that case, you can do something like that:

scrollView.post(new Runnable() { 
        public void run() { 
             scrollView.scrollTo(0, editText.getBottom());
        } 
});

or, if you want a smooth scroll instead of an instant scroll:

scrollView.post(new Runnable() { 
            public void run() { 
                 scrollView.smoothScrollTo(0, editText.getBottom());
            } 
    });

Obviously you can use any type of view instead of Edit Text. Note that getBottom() returns the coordinates of the view based on its parent layout, so all the views used inside the ScrollView should have only a parent (for example a Linear Layout).

If you have multiple parents inside the child of the ScrollView, the only solution i've found is to call requestChildFocus on the parent view:

editText.getParent().requestChildFocus(editText, editText);

but in this case you cannot have a smooth scroll.

I hope this answer can help someone with the same problem.

Thirtyeight answered 15/9, 2016 at 15:26 Comment(0)
R
21

Use something like this:

mScrollView.scrollBy(10, 10);

or

mScrollView.scrollTo(10, 10);
Religion answered 22/6, 2011 at 10:7 Comment(0)
G
9

Try using scrollTo method More Info

Guarneri answered 22/6, 2011 at 10:4 Comment(0)
Z
9

If you want to scroll instantly then you can use :

ScrollView scroll= (ScrollView)findViewById(R.id.scroll);
scroll.scrollTo(0, scroll.getBottom());

            OR

scroll.fullScroll(View.FOCUS_DOWN);

            OR

scroll.post(new Runnable() {            
    @Override
    public void run() {
           scroll.fullScroll(View.FOCUS_DOWN);              
    }
});

Or if you want to scroll smoothly and slowly so you can use this:

private void sendScroll(){
        final Handler handler = new Handler();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {Thread.sleep(100);} catch (InterruptedException e) {}
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.fullScroll(View.FOCUS_DOWN);
                    }
                });
            }
        }).start();
    }
Zebulon answered 11/12, 2014 at 6:38 Comment(2)
what does that catch block do?Wheresoever
Catch block is to catch exceptions during scrolling if found any.Zebulon
S
5

**to scroll up to desired height. I have come up with some good solution **

                scrollView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.scrollBy(0, childView.getHeight());
                    }
                }, 100);
Santonin answered 1/9, 2016 at 12:44 Comment(0)
I
5

Yes, you can.

Let's say you got one Layout and inside that, you got many Views. So if you want to scroll to any View programmatically, you have to write the following code snippet:

For example:

content_main.xml

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

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

    </LinearLayout>
</ScrollView>

MainActivity.java

ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
Button btn = (Button) findViewById(R.id.ivEventBanner);
TextView txtView = (TextView) findViewById(R.id.ivEditBannerImage);

If you want to scroll to a specific View, let's say txtview, in this case, just write:

scrollView.smoothScrollTo(txtView.getScrollX(),txtView.getScrollY());

And you are done.

Indissoluble answered 16/10, 2017 at 9:40 Comment(0)
C
4

I got this to work to scroll to the bottom of a ScrollView (with a TextView inside):

(I put this on a method that updates the TextView)

final ScrollView myScrollView = (ScrollView) findViewById(R.id.myScroller);
    myScrollView.post(new Runnable() {
    public void run() {
        myScrollView.fullScroll(View.FOCUS_DOWN);
    }
});
Carport answered 7/5, 2015 at 18:12 Comment(0)
P
3

Note: if you already in a thread, you have to make a new post thread, or it's not scroll new long height till the full end (for me). For ex:

void LogMe(final String s){
    runOnUiThread(new Runnable() {
        public void run() {
            connectionLog.setText(connectionLog.getText() + "\n" + s);
            final ScrollView sv = (ScrollView)connectLayout.findViewById(R.id.scrollView);
            sv.post(new Runnable() {
                public void run() {
                    sv.fullScroll(sv.FOCUS_DOWN);
                    /*
                    sv.scrollTo(0,sv.getBottom());
                    sv.scrollBy(0,sv.getHeight());*/
                }
            });
        }
    });
}
Parapsychology answered 15/6, 2014 at 8:51 Comment(0)
J
3

Adding another answer that does not involve coordinates.

This will bring your desired view to focus (but not to the top position) :

  yourView.getParent().requestChildFocus(yourView,yourView);

public void RequestChildFocus (View child, View focused)

child - The child of this ViewParent that wants focus. This view will contain the focused view. It is not necessarily the view that actually has focus.

focused - The view that is a descendant of child that actually has focus

Jez answered 1/8, 2015 at 17:49 Comment(1)
Exactly what i needed, thank you. First request focus for you scroll view and then scrollView.smoothScrollTo(0, scrollView.getChildAt(0).getBottom());Henpeck
S
3

Everyone is posting such complicated answers.

I found an easy answer, for scrolling to the bottom, nicely:

final ScrollView myScroller = (ScrollView) findViewById(R.id.myScrollerView);

// Scroll views can only have 1 child, so get the first child's bottom,
// which should be the full size of the whole content inside the ScrollView
myScroller.smoothScrollTo( 0, myScroller.getChildAt( 0 ).getBottom() );

And, if necessary, you can put the second line of code, above, into a runnable:

myScroller.post( new Runnable() {
    @Override
    public void run() {
        myScroller.smoothScrollTo( 0, myScroller.getChildAt( 0 ).getBottom() );
    }
}

It took me much research and playing around to find this simple solution. I hope it helps you, too! :)

Sudarium answered 13/12, 2015 at 20:51 Comment(0)
P
3

just page scroll:

ScrollView sv = (ScrollView) findViewById(your_scroll_view);
sv.pageScroll(View.FOCUS_DOWN);
Pick answered 13/4, 2017 at 17:3 Comment(0)
O
1

I was using the Runnable with sv.fullScroll(View.FOCUS_DOWN); It works perfectly for the immediate problem, but that method makes ScrollView take the Focus from the entire screen, if you make that AutoScroll to happen every time, no EditText will be able to receive information from the user, my solution was use a different code under the runnable:

sv.scrollTo(0, sv.getBottom() + sv.getScrollY());

making the same without losing focus on important views

greetings.

Ortiz answered 11/2, 2015 at 5:13 Comment(0)
D
1

it's working for me

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });
Dorolice answered 25/8, 2018 at 6:39 Comment(0)
G
0
private int totalHeight = 0;

ViewTreeObserver ScrollTr = loutMain.getViewTreeObserver();
ScrollTr.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            loutMain.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        } else {
            loutMain.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
        TotalHeight = loutMain.getMeasuredHeight();

    }
});

scrollMain.smoothScrollTo(0, totalHeight);
Gorski answered 28/5, 2019 at 12:25 Comment(0)
S
0
I had to create Interface

public interface ScrollViewListener {
    void onScrollChanged(ScrollViewExt scrollView, 
                         int x, int y, int oldx, int oldy);
}    

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;

public class CustomScrollView extends ScrollView {
    private ScrollViewListener scrollViewListener = null;
    public ScrollViewExt(Context context) {
        super(context);
    }

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

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

    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }
}




<"Your Package name ".CustomScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusableInTouchMode="true"
    android:scrollbars="vertical">

    private CustomScrollView scrollView;

scrollView = (CustomScrollView)mView.findViewById(R.id.scrollView);
        scrollView.setScrollViewListener(this);


    @Override
    public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
        // We take the last son in the scrollview
        View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1);
        int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));

        // if diff is zero, then the bottom has been reached
        if (diff == 0) {
                // do stuff
            //TODO keshav gers
            pausePlayer();
            videoFullScreenPlayer.setVisibility(View.GONE);

        }
    }
Spinous answered 4/7, 2019 at 11:1 Comment(0)
E
0
mScrollView.post { mScrollView.fullScroll(mScrollView.top)

I use this for scroll to top with kotlin

Extensity answered 28/3, 2023 at 8:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.