Android: ScrollView force to bottom

AndroidAndroid Scrollview

Android Problem Overview


I would like a ScrollView to start all the way at the bottom. Any methods?

Android Solutions


Solution 1 - Android

you should run the code inside the scroll.post like this:

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

Solution 2 - Android

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)
}

Solution 3 - Android

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)
}

Solution 4 - Android

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);

Solution 5 - Android

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());
     }
});

Solution 6 - Android

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.

Solution 7 - Android

i tried that successful.

scrollView.postDelayed(new Runnable() {
	@Override
	public void run() {
		scrollView.smoothScrollTo(0, scrollView.getHeight());
	}
}, 1000);

Solution 8 - Android

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:

https://stackoverflow.com/a/10209457/1310343

Solution 9 - Android

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).

Solution 10 - Android

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()          
}

Solution 11 - Android

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();
        }
    }
});

Solution 12 - Android

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.

Solution 13 - Android

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.

Solution 14 - Android

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);
  } 
});

Solution 15 - Android

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/

Solution 16 - Android

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());
      }
    }
  }
}

Solution 17 - Android

If your minimum SDK is 23 or upper you could use this:

View childView = findViewById(R.id.your_view_id_in_the_scroll_view)
if(childView != null){
  scrollview.post(() -> scrollview.scrollToDescendant(childView));
}

Solution 18 - Android

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.

Solution 19 - Android

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);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNoah SeidmanView Question on Stackoverflow
Solution 1 - Androidhungson175View Answer on Stackoverflow
Solution 2 - AndroidCommonsWareView Answer on Stackoverflow
Solution 3 - AndroidpeacepassionView Answer on Stackoverflow
Solution 4 - AndroidAjay ShresthaView Answer on Stackoverflow
Solution 5 - AndroidhttpsView Answer on Stackoverflow
Solution 6 - Androidademar111190View Answer on Stackoverflow
Solution 7 - AndroidYusuf YaşarView Answer on Stackoverflow
Solution 8 - AndroidFrankView Answer on Stackoverflow
Solution 9 - AndroidStephenDonaldHuffPhDView Answer on Stackoverflow
Solution 10 - AndroidLinhView Answer on Stackoverflow
Solution 11 - AndroidTeo InkeView Answer on Stackoverflow
Solution 12 - AndroidBarLrView Answer on Stackoverflow
Solution 13 - AndroidPhaestionView Answer on Stackoverflow
Solution 14 - AndroidnnyergesView Answer on Stackoverflow
Solution 15 - AndroidGhedeonView Answer on Stackoverflow
Solution 16 - AndroidAudi NugrahaView Answer on Stackoverflow
Solution 17 - AndroidMeLeanView Answer on Stackoverflow
Solution 18 - AndroidAndrewView Answer on Stackoverflow
Solution 19 - AndroidCrabsterView Answer on Stackoverflow