36

There is an app in the market place called Floating images. This app has one of the smoothest scrolling logic. Basically the app has a blank canvas covering whole screen and then there are some images displayed on top of the blank canvas. User can swipe and the app moves the image in the direction of swipe. Plus it does kinetic scrolling too. Plus there are no scrollbars so it seems like the developer has created a custom view implementing all smooth scrolling logic.

it would be awesome if i could get the source of it.. but anyone has any pseudo code or logic on how to implement this kind of feature. Any leads , site links would be helpful.

bigstones
  • 15,087
  • 7
  • 65
  • 82
prashant
  • 3,570
  • 7
  • 40
  • 50

2 Answers2

65

I have no experience with OpenGL nor accelerometer, but swipe (called fling in Android's API) is not hard to achieve. First thing you need when making such a custom View, is implementing a GestureDetector and call its onTouchEvent() in your view's onTouchEvent()

GestureDetector mGD = new GestureDetector(getContext(),
                                        new SimpleOnGestureListener() {

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
        // beware, it can scroll to infinity
        scrollBy((int)distanceX, (int)distanceY);
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float vX, float vY) {
        mScroller.fling(getScrollX(), getScrollY(),
                -(int)vX, -(int)vY, 0, (int)mMaxScrollX, 0, (int)mMaxScrollY);
        invalidate(); // don't remember if it's needed
        return true;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        if(!mScroller.isFinished() ) { // is flinging
            mScroller.forceFinished(true); // to stop flinging on touch
        }
        return true; // else won't work
    }
});

@Override
public boolean onTouchEvent(MotionEvent event) {
    return mGD.onTouchEvent(event);
}

While OnGestureListener.onScroll() calls directly View.scrollBy(), for the onFling() method you'll need a Scroller.

Scroller is a simple object that, as reference says, encapsulates scrolling. It can be used for continuous scrolling or to react to flings. Scroller.fling() begin a "simulation" of fling scroll inside itself, and by watching it you can copy its smoothness with a continuous redrawing animation:

@Override
protected void onDraw(Canvas canvas) {
    // ....your drawings....

    // scrollTo invalidates, so until animation won't finish it will be called
    // (used after a Scroller.fling() )
    if(mScroller.computeScrollOffset()) {
        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    }
}

that is, until animation is running, calculate the point we reached and scroll there.

As a last note: remember to return true in your OnGestureListener.onDown(), even if you don't want to do anything on down, or it won't work.

And be careful, because Scroller in Android 2.2 has a bug for which the fling animation will not actually end even if it reaches the limits you passed as arguments (yet computed offset respects them, so it won't actually move).

bigstones
  • 15,087
  • 7
  • 65
  • 82
  • 1
    Thanks bigstones. Looks like that i have to read some more to understand your sample and make my code work. I really appreciate your effort to provide code snippet and explanation. – prashant Feb 10 '11 at 13:39
  • Nice explanation bro for beginner but can you please tell me what is mScroller in this I mean where it is intialize ? – user1169079 Jun 14 '12 at 04:36
  • 1
    @user1201239 you can initalize it in the constructor. – bigstones Jun 14 '12 at 11:58
  • @bigstones : mScroller will be of the type ? am i right ? mScroller = new GestureDetector(context,this); mScroller.setOnDoubleTapListener(this); It wont be setonDOubleTapListener right ? – user1169079 Jun 20 '12 at 12:37
  • 1
    @user1201239, no it's `Scroller mScroller = new Scroller(this);` – bigstones Jun 20 '12 at 14:01
  • 1
    A complete example here: http://developer.android.com/training/custom-views/making-interactive.html – Snicolas May 03 '13 at 00:39
  • Thanx for this.. It helped me to start with scrolling bit..The problem is if the content is more than the area of screen and I try to scroll it still doesn't show the content and instead its all blank.. – Deepak Senapati May 31 '13 at 05:29
  • @bigstones can you help me on this.. http://stackoverflow.com/questions/26354263/catch-ontouch-event-by-custom-2d-scrollview-parent-handle-it-and-pass-to-childr – LOG_TAG Oct 14 '14 at 09:53
  • Thanks! Bigstones ! works fine! however I'm drawing shapeDrawables in _onDraw(Canvas canvas)_ when we scroll shapeDrawable's the bound changes ! is there any method to change/update the already displayed bounds ?? https://stackoverflow.com/questions/26376601/how-to-update-android-shapedrawable-bounds-changes-after-implimenting-scroller-w – LOG_TAG Oct 15 '14 at 07:21
8

The Floating Images app is an open source project. http://code.google.com/p/floatingimage/

rallat
  • 1,275
  • 1
  • 10
  • 16
  • 1
    @rallat : it'not relate to Android. – CoDe Oct 22 '11 at 08:05
  • 2
    @Shubh It is very much so Android related. He provided a link to an open source Android project called "floatingimage" with the app's description of "Show an image stream on your android phone" – rf43 Nov 29 '11 at 19:41