Programmatically scroll to end of screen

Haze picture Haze · Mar 18, 2017 · Viewed 16.8k times · Source

I have implemented TapTargetView library to my app.

After passing a certain element, I need to focus on the next view which is outside the screen at this moment:

@Override
public void onSequenceStep(TapTarget lastTarget) {
  if (lastTarget.id() == 7) {
     flavorContainer.setFocusableInTouchMode(true);
     flavorContainer.requestFocus();
  }
}

Everything was fine, before I added the ad unit at the bottom of the screen. So now the necessary element is displayed behind the ads.

enter image description here

Method requestFocus() scrolls layout only to the necessary view was visible but not to the end of screen.

enter image description here

I need a method that scrolls the contents of the screen to the VERY END, not just what would the necessary view become visible on the screen. Is it possible?

enter image description here

Layout structure

<android.support.design.widget.CoordinatorLayout>
<LinearLayout>
<android.support.v4.widget.NestedScrollView> 
<LinearLayout> 
<android.support.v7.widget.CardView> 
<LinearLayout>

</LinearLayout> 
</android.support.v7.widget.CardView> 
</LinearLayout> 
</android.support.v4.widget.NestedScrollView> 
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>

Answer

Giorgio Antonioli picture Giorgio Antonioli · Mar 18, 2017

You have two possible solutions with pros and cons.

First

Use the method fullScroll(int) on NestedScrollView. NestedScrollView must be drawn before using this method and the focus will be lost on the View that gained it before.

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

Second

Use the method scrollBy(int,int)/smoothScrollBy(int,int). It requires much more code, but you will not lose the current focus:

nestedScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        final int scrollViewHeight = nestedScrollView.getHeight();
        if (scrollViewHeight > 0) {
            nestedScrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            final View lastView = nestedScrollView.getChildAt(nestedScrollView.getChildCount() - 1);
            final int lastViewBottom = lastView.getBottom() + nestedScrollView.getPaddingBottom();
            final int deltaScrollY = lastViewBottom - scrollViewHeight - nestedScrollView.getScrollY();
            /* If you want to see the scroll animation, call this. */
            nestedScrollView.smoothScrollBy(0, deltaScrollY);
            /* If you don't want, call this. */
            nestedScrollView.scrollBy(0, deltaScrollY);
        }
    }
});