6

I need to implement a gallery which scrolls one item at a time, and which can do 'autoscroll': i.e. every couple of seconds, it automatically scrolls to the next item.

As per this thread: Android: Programmatically animate between images in Gallery widget, I extended Gallery, overriding onFling to ignore the fling event and instead simulate a DPAD arrow left or right in order to move a single item at a time:

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
          int kEvent;
          if(isScrollingLeft(e1, e2)){ //Check if scrolling left
            kEvent = KeyEvent.KEYCODE_DPAD_LEFT;
          }
          else{ //Otherwise scrolling right
            kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;
          }
          onKeyDown(kEvent, null);

          return true; 
    }

This works well. For the auto scroll, I create a handler and postDelayed a runnable which simulates the same DPAD key press in the same way:

handler.postDelayed(new Runnable() {
    public void run() { 
        onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
    }
}, AUTO_SCROLL_INTERVAL);

but this doesn't do anything!!

I know the runnable gets executed as expected at the correct interval, since I logged it and confirmed this, but the onKeyDown does not cause the gallery to scroll or switch items. Why would this work in one method and not another? I tried to call my onFling instead, to no avail. Also tried to dispatchKeyEvent, but no luck.

I really need to get this going, but I also really want to understand why the same code doesn't yield the same results in two different places... Does this have something to do with how Android views handle input events? I looked into the Gallery code for clues, but found nothing! It seems as though it should work.

Please, I'm stumped... any ideas?

Thanks

Community
  • 1
  • 1
noobler
  • 3,495
  • 4
  • 22
  • 26

3 Answers3

4

So, it turns out that the original logic I had does work. A custom gallery implementing that logic but stripped of everything else in my class (below) works as expected, so it must be something else in my class that is causing this problem.

Thanks for your help HighFlyer :)

At the very least I learned about reflection... which is a very cool feature of Java.

public class CustomGallery extends Gallery {

    private Handler handler;

    public CustomGallery(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        handler = new Handler();
        postDelayedScrollNext();
    }

    private void postDelayedScrollNext() {
        handler.postDelayed(new Runnable() {
            public void run() {
                postDelayedScrollNext();
                Log.d("CustomGallery", "dpad RIGHT");
                onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
            }
        }, 1000);
    }

    private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) {
        return e2.getX() > e1.getX();
    }

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        int kEvent;
        if (isScrollingLeft(e1, e2)) {
            Log.d("CustomGallery", "fling LEFT");
            kEvent = KeyEvent.KEYCODE_DPAD_LEFT;
        } else {
            Log.d("CustomGallery", "fling LEFT");
            kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;
        }
        onKeyDown(kEvent, null);
        return true;
    }
noobler
  • 3,495
  • 4
  • 22
  • 26
  • Dont understand it at all. Please explain result of calling onKeyDown in onFling method. Your implementation results that only one item scrolls at time. I'll be able to write sources only after 10 hours. – HighFlyer Nov 17 '11 at 20:47
  • @noobler Once it reached the last image it stops there. How to again make it move to first image? I meant like circular movement of images in gallery. Please help me how to do it. – Lavanya Feb 14 '14 at 07:22
2

Note for future visitors: a better solution in situations like this (full-view gallery) is to use a ViewPager. It works like a gallery, but properly implements a setCurrentItem() method for smooth scrolling. With the compatibility package, it works for API 4 (Android 1.6!) and up, so everyone can use it.

zeh
  • 10,130
  • 3
  • 38
  • 56
1

It seems like you call onKeyDown method of your activity, not gallery. Try call

gallery.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null)

instead. Correct me if I'm wrong

HighFlyer
  • 1,615
  • 2
  • 15
  • 22
  • Sorry, my post was unclear. The handler and the runnable are both inside my extended Gallery, so that the autoscroll logic is encapsulated in my custom view. – noobler Nov 16 '11 at 18:16
  • You said that overriden onFling works well. What does it mean? If you write in onFling only return true, you will still able to scroll images manually. See sources of Gallery widget http://codesearch.google.com/codesearch#uX1GffpyOZk/core/java/android/widget/Gallery.java&q=package:android.git.kernel.org%20file:android/widget/Gallery.java&l=1 and consider calling mFlingRunnable.startUsingDistance method via reflection – HighFlyer Nov 16 '11 at 19:02
  • You're right, scrolling still moves the items in the default way, but that's not a problem for me, since my gallery shows one full item at a time (thus making it impossible for a user to scroll through multiple items in one gesture). Thanks for the suggestion about reflection! I've never used reflection and didn't think it was possible to access private methods and types, but after googling it, it is possible! I'll try going that route... and post my results. thanks :) – noobler Nov 16 '11 at 20:06
  • Glad to help you. Waiting for your results. – HighFlyer Nov 17 '11 at 09:35
  • Thanks for your help HighFlyer.. I posted the answer above. I'd give you a vote up if i could :) – noobler Nov 17 '11 at 15:38