30

I have a situation in that I am using a horizontal scroll view with images and using buttons to smooth scroll to the different image locations. Now it works okay I was just wondering if anyone knew of anyway to slow down the smooth scroll method, i.e. having a longer annimation time? As currently the snapping happens pretty quickly.

Perhaps through an override of the smoothscroll, I have tried to search for this/examples but to no luck.

So any ideas?

Thanks,

Si

somin
  • 323
  • 1
  • 4
  • 12

7 Answers7

62

How About:

ObjectAnimator animator=ObjectAnimator.ofInt(yourHorizontalScrollView, "scrollX",targetXScroll );
animator.setDuration(800);
animator.start();
Saikat
  • 2,613
  • 1
  • 22
  • 14
  • 1
    If add animator.setDuration(800), works like a charm. – Sergey Vakulenko Oct 10 '13 at 08:45
  • 4
    This should be the selected answer. Apart from requiring API 11 or higher, it is the perfect solution. (In my library code, I have backed off to using `smoothScrollTo` when is before API 11). – darrenp Dec 10 '13 at 21:19
  • 1
    @darrenp you can use nineOldAndroids for backward compatibility all the way back to 1.0 (http://nineoldandroids.com/) – loeschg Jan 31 '14 at 16:44
  • Thank you. With animator.setDuration(800), it looks so nice. – anticafe Mar 07 '14 at 03:06
15

THis is one way, which works well for me:

    new CountDownTimer(2000, 20) { 

        public void onTick(long millisUntilFinished) { 
            hv.scrollTo((int) (2000 - millisUntilFinished), 0); 
        } 

        public void onFinish() { 

        } 
     }.start();

So here the horizontal scroll view (hv) moves in two seconds from position 0 to 2000 or to the end of the view if smaller than 2000px. Easy to adjust...

Lumis
  • 21,517
  • 8
  • 63
  • 67
  • @Lumis Hey thanks for the response though I think creating a new timer obj to just scroll slower might be a bit too much, also what would happen if in the period counting down the user performs another action, would it then continue with the previous and start off a new one? I guess unless a flag was set to prevent this happening, and maybe setting it in the onFinish to allow new interation... Though could this be misconstrued as a slow responding UI? – somin Mar 11 '11 at 11:02
  • It all of course depends on what interaction your activity has, but I think the best is to try, experiment, and see how it performs. Note that this object may have a stop() method, which I did not try, so you may be able to stop and restart it from any point. You are right that this is an overkill but if there is no easier way to do it then at least this works fine. I am using it in my game which is in the market. – Lumis Mar 11 '11 at 11:17
  • Yeh I did some experimenting earlier with the CountDownTimer (in another aspect of the game that required a simple counter) the only problem was that this timer required resetting at points, which seems to be a problem with the count down timer, because I tried calling Cancel on it, didnt work, setting to null, and it would still continue, was quite bizzare. Ended up creating a seperate thread, anyway, so I have lost faith in the CountDownTimer obj. – somin Mar 15 '11 at 11:48
  • I did resolve this instead by using some code someone posted on here (i would link, but have just spent the past 5 mins searching and cant find the post sorry), if i remember I'll post it when i get home. It basically programmatically worked out where to scroll to and using total view widths/over number of views etc and used that in the smooth scroll method. – somin Mar 15 '11 at 11:51
  • 1
    Yes, smoothScrollTo(int x, int y), but somebody complained that is too fast and there seems to be no option to adjust speed. – Lumis Mar 15 '11 at 13:49
  • oh sorry, i put that comment to the wrong question lol, was meant to be another one i was looking at, thought it was a question about smooth scroll snapping to locations – somin Mar 17 '11 at 11:54
13

Subclass HorizontalScrollView, use reflection to get access to the private field mScroller in HorizontalScrollView. Of course, this will break if the underlying class changes the field name, it defaults back to original scroll implemenation.

The call myScroller.startScroll(scrollX, getScrollY(), dx, 0, 500); changes the scroll speed.

private OverScroller myScroller;     

private void init()
{
    try
    {
        Class parent = this.getClass();
        do
        {
            parent = parent.getSuperclass();
        } while (!parent.getName().equals("android.widget.HorizontalScrollView"));

        Log.i("Scroller", "class: " + parent.getName());
        Field field = parent.getDeclaredField("mScroller");
        field.setAccessible(true);
        myScroller = (OverScroller) field.get(this);

    } catch (NoSuchFieldException e)
    {
        e.printStackTrace();
    } catch (IllegalArgumentException e)
    {
        e.printStackTrace();
    } catch (IllegalAccessException e)
    {
        e.printStackTrace();
    }
}

public void customSmoothScrollBy(int dx, int dy)
{
    if (myScroller == null)
    {
        smoothScrollBy(dx, dy);
        return;
    }

    if (getChildCount() == 0)
        return;

    final int width = getWidth() - getPaddingRight() - getPaddingLeft();
    final int right = getChildAt(0).getWidth();
    final int maxX = Math.max(0, right - width);
    final int scrollX = getScrollX();
    dx = Math.max(0, Math.min(scrollX + dx, maxX)) - scrollX;

    myScroller.startScroll(scrollX, getScrollY(), dx, 0, 500);
    invalidate();
}

public void customSmoothScrollTo(int x, int y)
{
    customSmoothScrollBy(x - getScrollX(), y - getScrollY());
}
Wei
  • 161
  • 1
  • 3
  • Works great for vertical scroll also (with some minor additions). As a safeguard, one could write their own scroller possibly? Also Note: `OverScroller` is API 9 and NOT a subclass of `Scroller`. – pjco Mar 28 '13 at 22:48
  • @pjco can you post the those changes you made for vertical scrolling. I am having hard time making it work. – Varundroid May 30 '13 at 03:48
  • Sure, have a look here are my changes: https://gist.github.com/patrickcousins/5699691 Only changed a few values in `customSmoothScrollBy` – pjco Jun 03 '13 at 17:19
1

Its a scroller the scroll automatically and continously. It was made to show a credits screen by continously scrolling through a list of images. This might help you or give you some idea.

https://github.com/blessenm/SlideshowDemo

Parag Chauhan
  • 35,760
  • 13
  • 86
  • 95
0

Use .smoothScrollToPositionFromTop instead. Example

listView.smoothScrollToPositionFromTop(scroll.pos(),0,scroll.delay());

wherescroll is a simple variable from a class that takes current screen position .get() returns new position .pos() and time of smooth scrolling .delay ... etc

0

Or even easier, .smoothScrollTo(). Example:

hsv.smoothScrollTo(x, y);

Docs: Android Developer ScrollView docs

CharlesA
  • 4,260
  • 2
  • 25
  • 31
-5

Have a look at http://developer.android.com/reference/android/widget/Scroller.html:

The duration of the scroll can be passed in the constructor and specifies the maximum time that the scrolling animation should take

Elepferd
  • 156
  • 4
  • 1
    HorizontalScrollView has no setScroller method, it has its own set of scroll properties. How would one attach a Scroller to the horizontalscrollview, then? – Turnsole Mar 04 '11 at 22:54
  • Would you have to create your own and override the properties from in there? – somin Mar 11 '11 at 11:05