12

Context: I have a ScrollView that may have children added to its content view during a fling. Since the fling is configured with the height of the ScrollView contents before those children are added, if children get added then the fling stops itself (and actually scrolls backwards a bit because of overscroll) even though it hasn't reached the bottom of the contents.

I can possibly restart the fling using #fling(int velocity), but I can't figure out a way to get the current fling velocity or stop the current fling. Any ideas?

Foxichu
  • 952
  • 10
  • 22
  • I would recommend to handle this issue like an array. Put always twice as much (or more) elements in the list as you need. The second half of elements, that you don't have now, are empty. If you add an element, do not add it, but fill the next empty element with the new data. If the list scroll enters the last element that is filled, stop the fling. This way, you will always have a ongoing fling. – JacksOnF1re Aug 05 '15 at 15:14
  • @Foxichu, I am also facing issue,kindly share some code to resolve this issue.As you mentioned you solved this issue using nested scrollview code.Please share that .Thanks in advance. – gireesh Chanti Apr 27 '17 at 09:50

2 Answers2

8

To answer your questions from the prompt:

  • There are no APIs to get the current velocity of ScrollView.
  • You can stop the current fling by careful handling of touch events as described in a previous SO post.

Looking at the ScrollView source code, it uses an OverScroller to handle the fling events. There are two ways of approaching this:

  1. Use reflection to access the mScroller private field within ScrollView. Once you have accessed it you can get the current velocity through its public API: public float getCurrVelocity(); Using reflection is never ideal since you have to worry about it breaking across android versions, but a simple isolated usage can be relatively efficient.
  2. Override the fling() method in ScrollView and instantiate a OverScroller to keep track of the scrolling. If all goes well, your Overscoller will always be in the same state as the one within ScrollView.

Something like this:

@Override
public void fling(int velocityY)
{
    // Pass through fling to parent
    super.fling(velocityY);

    // Keep track of velocity using our own Overscoller instance
    mOurOverscroller = mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0,
    Math.max(0, bottom - height), 0, height/2);
}
Community
  • 1
  • 1
Trevor Carothers
  • 2,250
  • 11
  • 19
  • 1
    Alternate approach I ended up going with: fork the NestedScrollView code from the support library (i.e. copy it to a new class) and edit it as needed. – Foxichu Dec 06 '15 at 17:29
2

I solved a similar problem with @Override fling method. If you override fling method on your ScrollViewNoFling class and not call super.fling on this method, you gonna have not-fling-handled scrollView.

@Override
public void fling (int velocity)
{
    /*Scroll view is no longer going to handle scroll velocity.
     * super.fling(velocity);
    */
}
arodriguezdonaire
  • 5,396
  • 1
  • 26
  • 50