Ishaan Garg
Ishaan Garg

Reputation: 3093

Stop scrollView scrolling on user touch

I'm automatically scrolling the scrollView to the view's bottom.

scrollView.smoothScrollTo(0, scrollView.getBottom());

If the user touches the layout, I need the scrolling to stop & stay at the current position.

scrollView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                //// TODO: 01/08/16 STOP SCROLLING
            }
            return false;
        }
    });

I've tried to smoothScrollBy(0,0); but it's not working.

Upvotes: 0

Views: 2335

Answers (2)

Ishaan Garg
Ishaan Garg

Reputation: 3093

Well I solved it by using an ObjectAnimator. It not only elegantly worked as a solution but also gave me control on the scrolling speed.

I replaced

scrollView.smoothScrollTo(0, scrollView.getBottom());

with

objectAnimator = ObjectAnimator
                .ofInt(scrollView, "scrollY", scrollView.getBottom())
                .setDuration(3000);
objectAnimator.start();

and then

scrollView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    objectAnimator.cancel();
                }
                return false;
            }
        });

Upvotes: 1

ahdgfd
ahdgfd

Reputation: 325

One approach may be to use smoothScrollToPosition, which stops any existing scrolling motion. Note this method requires API level >= 8 (Android 2.2, Froyo).

Note that if the current position is far away from the desired position, then the smooth scrolling will take quite a long time and look a bit jerky (at least in my testing on Android 4.4 KitKat). I also found that a combination of calling setSelection and smoothScrollToPosition could sometimes causes the position to "miss" slightly, this seems to happen only when the current position was very close to the desired position.

In my case, I wanted my list to jump to the top (position=0) when the user pressed a button (this is slightly different from your use case, so you will need to adapt this to your needs).

I used the following method to

private void smartScrollToPosition(ListView listView, int desiredPosition) {
    // If we are far away from the desired position, jump closer and then smooth scroll
    // Note: we implement this ourselves because smoothScrollToPositionFromTop
    // requires API 11, and it is slow and janky if the scroll distance is large,
    // and smoothScrollToPosition takes too long if the scroll distance is large.
    // Jumping close and scrolling the remaining distance gives a good compromise.
    int currentPosition = listView.getFirstVisiblePosition();
    int maxScrollDistance = 10;
    if (currentPosition - desiredPosition >= maxScrollDistance) {
        listView.setSelection(desiredPosition + maxScrollDistance);
    } else if (desiredPosition - currentPosition >= maxScrollDistance) {
        listView.setSelection(desiredPosition - maxScrollDistance);
    }
    listView.smoothScrollToPosition(desiredPosition); // requires API 8
}

In my action handler for the button I then called this as follows

case R.id.action_go_to_today:
    ListView listView = (ListView) findViewById(R.id.lessonsListView);
    smartScrollToPosition(listView, 0); // scroll to top
    return true;

The above does not directly answer your question, but if you can detect when the current position is at or near your desired position, then maybe you could use smoothScrollToPosition to stop the scrolling.

Upvotes: 0

Related Questions