I would like a ScrollView to start all the way at the bottom. Any methods?
-
1I think its just scrollTo(), yea I just checked the dev docs for ScrollView. Easy peasy. – Noah Seidman Jun 20 '10 at 18:30
19 Answers
you should run the code inside the scroll.post like this:
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});

- 4,373
- 6
- 22
- 21
-
4there's some way without lose focus current element, when i do this i lose the focus of my current element (different from scrollview) – rkmax Sep 21 '14 at 16:48
-
2This is needed only in cases where the layout has not yet been measured and layouted (for example if you run it in onCreate). In cases like pressing a button, .post() is not needed. – Patrick Boos Jan 12 '15 at 13:44
-
21If you don't want to focus on the ScrollView, you can use `scroll.scrollTo(0, scroll.getHeight());` to jump to the bottom, or `scroll.smoothScrollTo(0, scroll.getHeight());` for a smoother scroll – yuval Apr 26 '16 at 23:55
-
Isn't this code a possible memory leak? An anonymous Runnable is created that holds a reference to an activity (scroll)view. If the activity gets destroyed while the runnable is executing its task, it will leak a reference to the scrollview, no? – Jenever Jan 19 '18 at 08:43
-
3In Kotlin: `scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }` – Albert Vila Calvo May 27 '19 at 13:12
-
@AlbertVilaCalvo, the code in your comment worked for me and took my scroll to the very end. Most of the solutions here were stopping the scroll slightly before the end for me. Thanks !! – Nafeez Quraishi Nov 17 '20 at 18:19
scroll.fullScroll(View.FOCUS_DOWN)
also should work.
Put this in a scroll.Post(Runnable run)
Kotlin Code
scrollView.post {
scrollView.fullScroll(View.FOCUS_DOWN)
}

- 6,799
- 4
- 25
- 42

- 986,068
- 189
- 2,389
- 2,491
-
6That doesn't seem to do anything, any suggestions? I tried it on onCreate and later in the onClick of a button. – RichardJohnn Aug 02 '10 at 18:50
-
It doesn't seems to work on changing orientation. Otherwise its working. – Prashant Mar 19 '15 at 07:30
-
1This doesn't work if the layout size has changed right before calling it. It needs to be posted instead. – MLProgrammer-CiM Apr 09 '15 at 15:32
-
5This and below, won't work until you give some time to the view to inflate fully, just simplifying ademar answer. scrollView.postDelayed(new Runnable() { @Override public void run() { scrollView.fullScroll(View.FOCUS_UP // Or Down); } }, 1000); – EngineSense Dec 31 '15 at 00:44
-
1scroll.fullScroll(View.FOCUS_DOWN) will lead to the change of focus. That will bring some strange behavior when there are more than one focusable views, e.g two EditText. Check another solution I provide at the bottom. – peacepassion Jan 19 '16 at 00:38
-
`scroll.fullScroll(View.FOCUS_DOWN)` will lead to the change of focus. That will bring some strange behavior when there are more than one focusable views, e.g two EditText. Check my answer below. – peacepassion Sep 02 '17 at 07:08
-
-
In those case were scroll.scrollTo(0, sc.getBottom()) don't work, use scroll.post. Example: scroll.post(new Runnable() { @Override public void run() { scroll.fullScroll(View.FOCUS_DOWN); } }); – nnyerges Feb 27 '19 at 18:37
-
@eCDroid: That was not in my original answer; it was added in an edit. Based on some of the other answers on the question, my guess is that the concern is whether the `ScrollView` is laid out at the time of the `fullScroll()` call. If so, a more efficient approach, if you are using Kotlin, is to use [`doOnLayout` from Android KTX](https://developer.android.com/reference/kotlin/androidx/core/view/package-summary#doonlayout). – CommonsWare May 05 '20 at 10:30
-
@EngineSense That was exactly my issue, i thought nothing worked, but the layout simply needed some milliseconds to adjust to new size! (I used 500 ms btw) – Big_Chair Aug 29 '20 at 12:49
-
scroll.fullScroll(View.FOCUS_DOWN)
will lead to the change of focus. That will bring some strange behavior when there are more than one focusable views, e.g two EditText. There is another way for this question.
View lastChild = scrollLayout.getChildAt(scrollLayout.getChildCount() - 1);
int bottom = lastChild.getBottom() + scrollLayout.getPaddingBottom();
int sy = scrollLayout.getScrollY();
int sh = scrollLayout.getHeight();
int delta = bottom - (sy + sh);
scrollLayout.smoothScrollBy(0, delta);
This works well.
Kotlin Extension
fun ScrollView.scrollToBottom() {
val lastChild = getChildAt(childCount - 1)
val bottom = lastChild.bottom + paddingBottom
val delta = bottom - (scrollY+ height)
smoothScrollBy(0, delta)
}
Or if you want to further enhance to check whether it is already at the bottom before scrolling, you can do something like this:
fun ScrollView.scrollToBottom() {
val lastChild = children.lastOrNull() ?: return
val bottom = lastChild.bottom + paddingBottom
val currentY = height + scrollY
val alreadyAtBottom = bottom <= currentY
if (!alreadyAtBottom) {
val delta = bottom - currentY
smoothScrollBy(0, delta)
} else {
// already at bottom, do nothing
}
}

- 173
- 1
- 16

- 1,918
- 2
- 15
- 19
-
So glad I didn't have to waste any more time on this. Just what I needed – Alexandre G May 16 '16 at 04:18
-
8
-
1
-
1Tried everything else on this page, even the stuff way below this. This was the only thing that worked, and it doesn't cause my EditText to lose focus. Thank you. – Joel Jan 05 '17 at 02:58
-
If you need to scroll down while keyboard is showing up, combine this code with [this library](https://github.com/yshrsmz/KeyboardVisibilityEvent). Works like a charm. – wonsuc Jan 19 '18 at 20:06
-
-
-
ScrollView only has one child which is a ViewGroup so you can just say ```val lastChild = getChildAt(0) ``` – Ian Elvister Mar 12 '21 at 02:10
-
-
This is the best answer. Doesn't look hacky and scrolls smoothly. If you need this behaviour in your on create method, be sure to wrap it in a postDelayed block or wait for the view layout to be fully layed out – Alfred Afutu Jun 28 '21 at 11:08
Sometimes scrollView.post doesn't work
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
BUT if you use scrollView.postDelayed, it will definitely work
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
},1000);

- 2,433
- 1
- 21
- 25
-
-
-
1Just remember that you need to dispose of your Runnable when you finish the activity – FabioR Aug 22 '19 at 18:53
-
What worked best for me is
scroll_view.post(new Runnable() {
@Override
public void run() {
// This method works but animates the scrolling
// which looks weird on first load
// scroll_view.fullScroll(View.FOCUS_DOWN);
// This method works even better because there are no animations.
scroll_view.scrollTo(0, scroll_view.getBottom());
}
});

- 429
- 1
- 6
- 8
-
I tried this, but the algorithm here is wrong. Check my answer at the bottom please. – peacepassion Jan 19 '16 at 00:37
I increment to work perfectly.
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();
}
Note
This answer is a workaround for really old versions of android. Today the postDelayed
has no more that bug and you should use it.

- 14,215
- 14
- 85
- 114
-
3Not above two, but this works well in my phone (LG JellyBean 4.1.2 Optimus G). – Youngjae May 29 '13 at 07:43
-
10
-
1@MattWolfe at the time does not worked in some old versions of android. But today this answer is deprecated at all. – ademar111190 Aug 14 '14 at 19:31
-
5For the love of god, use scrollView.postDelayed(runnable, 100)! :) – Alex Lockwood Jan 04 '16 at 23:17
-
1I added a note @AlexLockwood I hope the people use the `postDelayed` :) – ademar111190 Jan 05 '16 at 17:15
i tried that successful.
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, scrollView.getHeight());
}
}, 1000);

- 191
- 2
- 5
Here is some other ways to scroll to bottom
fun ScrollView.scrollToBottom() {
// use this for scroll immediately
scrollTo(0, this.getChildAt(0).height)
// or this for smooth scroll
//smoothScrollBy(0, this.getChildAt(0).height)
// or this for **very** smooth scroll
//ObjectAnimator.ofInt(this, "scrollY", this.getChildAt(0).height).setDuration(2000).start()
}
Using
If you scrollview already laid out
my_scroll_view.scrollToBottom()
If your scrollview is not finish laid out (eg: you scroll to bottom in Activity onCreate
method ...)
my_scroll_view.post {
my_scroll_view.scrollToBottom()
}

- 57,942
- 23
- 262
- 279
When the view is not loaded yet, you cannot scroll. You can do it 'later' with a post or sleep call as above, but this is not very elegant.
It is better to plan the scroll and do it on the next onLayout(). Example code here:
One thing to consider is what NOT to set. Make certain your child controls, especially EditText controls, do not have the RequestFocus property set. This may be one of the last interpreted properties on the layout and it will override gravity settings on its parents (the layout or ScrollView).

- 780
- 6
- 18
Not exactly the answer to the question, but I needed to scroll down as soon as an EditText got the focus. However the accepted answer would make the ET also lose focus right away (to the ScrollView I assume).
My workaround was the following:
emailEt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
Toast.makeText(getActivity(), "got the focus", Toast.LENGTH_LONG).show();
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}, 200);
}else {
Toast.makeText(getActivity(), "lost the focus", Toast.LENGTH_LONG).show();
}
}
});

- 5,928
- 4
- 38
- 37
I actually found that calling fullScroll twice does the trick:
myScrollView.fullScroll(View.FOCUS_DOWN);
myScrollView.post(new Runnable() {
@Override
public void run() {
myScrollView.fullScroll(View.FOCUS_DOWN);
}
});
It may have something to do with the activation of the post() method right after performing the first (unsuccessful) scroll. I think this behavior occurs after any previous method call on myScrollView, so you can try replacing the first fullScroll() method by anything else that may be relevant to you.

- 139
- 1
- 5
Using there is another cool way to do this with Kotlin coroutines. The advantage of using a coroutine opposed to a Handler with a runnable (post/postDelayed) is that it does not fire up an expensive thread to execute a delayed action.
launch(UI){
delay(300)
scrollView.fullScroll(View.FOCUS_DOWN)
}
It is important to specify the coroutine's HandlerContext as UI otherwise the delayed action might not be called from the UI thread.

- 63
- 8
In those case were using just scroll.scrollTo(0, sc.getBottom()) don't work, use it using scroll.post
Example:
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});

- 563
- 4
- 15
One possible reason of why scroll.fullScroll(View.FOCUS_DOWN)
might not work even wrapped in .post()
is that the view is not laid out. In this case View.doOnLayout() could be a better option:
scroll.doOnLayout(){
scroll.fullScroll(View.FOCUS_DOWN)
}
Or, something more elaborated for the brave souls: https://chris.banes.dev/2019/12/03/suspending-views/
A combination of all answers did the trick for me:
Extension Function PostDelayed
private fun ScrollView.postDelayed(
time: Long = 325, // ms
block: ScrollView.() -> Unit
) {
postDelayed({block()}, time)
}
Extension Function measureScrollHeight
fun ScrollView.measureScrollHeight(): Int {
val lastChild = getChildAt(childCount - 1)
val bottom = lastChild.bottom + paddingBottom
val delta = bottom - (scrollY+ height)
return delta
}
Extension Function ScrolltoBottom
fun ScrollView.scrollToBottom() {
postDelayed {
smoothScrollBy(0, measureScrollHeight())
}
}
Be aware that the minimum delay should be at least 325ms or the scrolling will be buggy (not scrolling to the entire bottom). The larger your delta between the current height and the bottom is, the larger should be the delayed time.

- 4,264
- 1
- 21
- 65
Some people here said that scrollView.post didn't work.
If you don't want to use scrollView.postDelayed, another option is to use a listener. Here is what I did in another use case :
ViewTreeObserver.OnPreDrawListener viewVisibilityChanged = new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (my_view.getVisibility() == View.VISIBLE) {
scroll_view.smoothScrollTo(0, scroll_view.getHeight());
}
return true;
}
};
You can add it to your view this way :
my_view.getViewTreeObserver().addOnPreDrawListener(viewVisibilityChanged);

- 16
This works instantly. Without delay.
// wait for the scroll view to be laid out
scrollView.post(new Runnable() {
public void run() {
// then wait for the child of the scroll view (normally a LinearLayout) to be laid out
scrollView.getChildAt(0).post(new Runnable() {
public void run() {
// finally scroll without animation
scrollView.scrollTo(0, scrollView.getBottom());
}
}
}
}

- 640
- 7
- 7