11

I have a NestedScrollView populated with a vertical LinearLayout, which itself has a bunch of children of various view types: multiple TextViews, two static GridViews, and even a FrameLayout to show a Fragment beneath all of this.

When pressing the back button, if the user has scrolled below a certain point, instead of finishing the Activity, the "scrollToTop" method is called:

public static void scrollToTop(final NestedScrollView scrollview) {
    new Handler().postDelayed(new Runnable() {
        public void run() {
            scrollview.fullScroll(NestedScrollView.FOCUS_UP);
        }
    }, 200);
}

This works in the previous version of my app, which is in the Play Store. But now, after updating my app to target Android Oreo (and updating the support library to version 26.0.2), instead of scrolling to the top, it seems to start scrolling from below the NestedScrollView's original scroll position, and stops where it was. So it just appears as a weird stutter. At some positions, however, it does scroll to the top (albeit very rarely and inconsistently), and others it actually scrolls to the bottom, for what reason I don't understand.

I have been experimenting with view focusability, to no avail. For example, I read that the Static GridViews may interrupt focus while scrolling. I've also tried various different methods to scroll up, such as

scrollview.pageScroll(View.FOCUS_UP);

and

scrollview.smoothScrollTo(0,0);

But nothing seems to work. Is there something wrong with the support library this time around?

S Fitz
  • 1,014
  • 14
  • 29
  • add `android:descendantFocusability="blocksDescendants"` to the `LinearLayout` inside `NestedScrollView` and this also `NestedScrollView.scrollTo(0, 0); ` – AskNilesh Sep 11 '17 at 13:30
  • That's... actually pretty incredible that that worked. More so that all of the above (smoothScrollTo, pageScroll, fullScroll) DON'T work, but scrollTo does work. I have to sacrifice the smoothness of smoothScrollTo, but it's better than before. Huge thanks! – S Fitz Sep 12 '17 at 08:49
  • to programmatically scroll to anywhere, check this: https://stackoverflow.com/questions/52083678/nestedscrollviews-smoothscrollto-behaves-weird – user1506104 Sep 10 '18 at 17:02

4 Answers4

19

try this

add android:descendantFocusability="blocksDescendants" to the LinearLayout inside NestedScrollView and this also

to scroll to top of NestedScrollView use this

NestedScrollView.scrollTo(0, 0);

Edit

Use fling() and smoothScrollTo togather

nestedScrollView.post(new Runnable() {
   @Override
   public void run() {
      nestedScrollView.fling(0);
      nestedScrollView.smoothScrollTo(0, 0);
   }
});
AskNilesh
  • 58,437
  • 15
  • 99
  • 129
14

UPDATE:

Found a better solution. Try this combo:

scrollView.fling(0);  // Sets mLastScrollerY for next command
scrollView.smoothScrollTo(0, 0);  // Starts a scroll itself

Looks like a hack, but works well on both my devices (tested with Support Library 26.0.0 & 27.0.2). Can be used to scroll smoothly to any other position. Based on the idea that the problem lies in missing update of mLastScrollerY.

Please leave a feedback if it works for you or not.

Original answer:

Hit this issue too.

NestedScrollView.smoothScrollTo(0, 0) worked in Support Library up to 25.4.0, and doesn't work since 26.0.0 up to current 27.0.2. The contents of NestedScrollView doesn't matter (some TextViews are enough).

This bug is already reported twice on Google Issue Tracker. Minimal project to reproduce it can be found on GitHub.

Found two working solutions:

  1. NestedScrollView.scrollTo(0, 0) (see accepted answer, jumps abruptly)
  2. NestedScrollView.fling(-10000) (scrolls smoothly, but appropriate velocity value depends on current position, device, desired scrolling time and so on)

It was not necessary to change focusability in my case.

gmk57
  • 539
  • 5
  • 15
  • 1
    Thanks, `fling(-10000)` is only solution working for me. Do you know how to calculate `velocityY` depending on the height of content? – Fori Feb 09 '18 at 23:10
  • `NestedScrollView.smoothScrollTo` doesn't work for me even using 27.0.2. NestedScrollView is jumping on the place, instead of scroll to top. – Konstantin Konopko Feb 16 '18 at 18:39
  • @Fori, I'm not sure if any reliable universal formula exists. Increasing velocity by 2 raises distance by 3.333..., but same velocity on different devices gives different distance. So `requiredVelocity = (int) -Math.pow(scrollView.getScrollY() * deviceFactor, 0.5752)`. For stopping slowly at the top, `deviceFactor` should be 1417 on my phone and 1146 on my tablet, but I don't know how to determine it for any arbitrary device (it is not proportional to screen density). On the other hand, original `pageScroll`/`smoothScrollTo` always overscrolled, so we may use higher values (2000?). – gmk57 Feb 18 '18 at 21:43
  • 1
    @KonstantinKonopko Yes, the **last** version where `smoothScrollTo` worked was 25.4.0. Try `fling`. – gmk57 Feb 18 '18 at 21:48
4

This code works for me.

scrollView.post {
    scrollView.fling(0)
    scrollView.fullScroll(ScrollView.FOCUS_UP)
}
WuHaojie
  • 85
  • 6
0

It seems to it's finally fixed in 28.0.0 Support lib, so NestedScrollView.smoothScrollTo() works as expected for me

Konstantin Konopko
  • 4,533
  • 4
  • 28
  • 52