29

I loaded some images into a gallery. Now I'm able to scroll but once started scrolling the scrolling won't stop. I would like the gallery to just scroll to the next image and then stop until the user does the scroll gesture again.

this is my code

import android.widget.ImageView;
import android.widget.Toast;
 import android.widget.AdapterView.OnItemClickListener;

public class GalleryExample extends Activity {

private Gallery gallery;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

     gallery = (Gallery) findViewById(R.id.examplegallery);
     gallery.setAdapter(new AddImgAdp(this));

     gallery.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView parent, View v, int position, long id) {

            Toast.makeText(GalleryExample.this, "Position=" + position, Toast.LENGTH_SHORT).show();
        }
    });

}

public class AddImgAdp extends BaseAdapter {
    int GalItemBg;
    private Context cont;


    private Integer[] Imgid = {
            R.drawable.a_1, R.drawable.a_2, R.drawable.a_3, R.drawable.a_4, R.drawable.a_5, R.drawable.a_6, R.drawable.a_7
    };

    public AddImgAdp(Context c) {
        cont = c;
        TypedArray typArray = obtainStyledAttributes(R.styleable.GalleryTheme);
        GalItemBg = typArray.getResourceId(R.styleable.GalleryTheme_android_galleryItemBackground, 0);
        typArray.recycle();
    }

    public int getCount() {
        return Imgid.length;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imgView = new ImageView(cont);

        imgView.setImageResource(Imgid[position]);

        i.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imgView.setBackgroundResource(GalItemBg);

        return imgView;
    }
}

}

and the xmlLayout file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android" >
<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/examplegallery"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />
</LinearLayout>
Andro Selva
  • 53,910
  • 52
  • 193
  • 240

7 Answers7

48

I think I found a way to achieve both only scrolling 1 view at a time in the gallery and be able to have a minimal swipe length to trigger animation.

Override the onFling method of the gallery widget and instead of calling super.onFling, check to see whether or not the swipe was from left to right or right to left and call the appropriate dpad event as shown below:

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

@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;  
}
Nadewad
  • 763
  • 6
  • 7
  • 3
    You, sir, are one smart fox. Thank you for this elegant solution - exactly what I needed to make my gallery usable. – sniurkst Dec 20 '10 at 15:47
  • 3
    Exactly what I was looking for. Just to clarify to this solution, I was not able to figure out how to set onFling() inline and had to resort to creating a custom Gallery instead. This solution helped me out to the end: http://stackoverflow.com/questions/4582123/creating-a-custom-gallery-overriding-onfling – Artem Russakovskii Feb 25 '11 at 22:55
  • This works perfet for me except that if i try to scroll(not fling) an image say left image to the center, by the time i reach the center,the left image reaches the center .how to prevent that??? – Pravy Jun 30 '11 at 11:34
  • I'm sorry I'm not quite sure what you're asking. Could you be more specific? – Nadewad Jul 18 '11 at 20:53
  • Hah, nice, but how pitiful that we must look for such workarounds instead of one simple attribute... – Fenix Voltres Mar 19 '12 at 15:24
  • @Nadewad i used ur code in my gallery app, but it still not working for me. No doubt it slowed down my scroll. Previously 15 to images are scrolled at a time but now 2 to 3 images are scrolled at one scroll event. So can you help me a bit. – Chandra Sekhar Jun 18 '12 at 13:43
  • @chandra-sekhar Just add this together with the code above and it will always scroll one image at a time: ` @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return true; } ` – Andrew Chen Aug 11 '15 at 23:59
12

This is the code that worked for me.

Nadewad's solution + some animation speed adjustments:

Create class that extends Gallery, and override this metods:

  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    setAnimationDuration(600);
    return super.onScroll(e1, e2, distanceX, distanceY);
  }

  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    float velMax = 2500f;
    float velMin = 1000f;
    float velX = Math.abs(velocityX);
    if (velX > velMax) {
      velX = velMax;
    } else if (velX < velMin) {
      velX = velMin;
    }
    velX -= 600;
    int k = 500000;
    int speed = (int) Math.floor(1f / velX * k);
    setAnimationDuration(speed);

    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;
  }

Enjoy!

peceps
  • 17,370
  • 11
  • 72
  • 79
3

The easy way is following:

@Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        return super.onFling(e1, e2, 0, velocityY);
    }

You also can check here: Android Infinite Loop Gallery

Andro Selva
  • 53,910
  • 52
  • 193
  • 240
James
  • 5,119
  • 5
  • 25
  • 27
  • This one works the best for me because it makes the gallery scroll only one at a time no matter how fast you swipe. I have tried the KeyEvent solution and if you swiped too fast, it will skip like two or three. – Andrew Chen Aug 11 '15 at 01:20
2

no need to do any thing simply return false

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

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
  return false;  
}

it worked for me

anshul
  • 982
  • 1
  • 11
  • 33
2

The easiest way I have found to accomplish this is by overriding the Gallery onFling method, and providing my own velocityX value:

@Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        return super.onFling(e1, e2, 10, velocityY);
    }

It's not perfect, but it does the job. Ideally, you would probably write something custom for onFling to make it work exactly as you like.

Tim H
  • 13,513
  • 3
  • 17
  • 9
2

I found the following override on onFling worked nicely enough for small swipes and single page pagination:

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 
{
    boolean leftScroll = isScrollingLeft(e1, e2);

    float velX;
    if(leftScroll)
    {
        velX=500;
    }
    else
    {
        velX=-500;
    }

    return super.onFling(e1, e2, velX, velocityY);
}

The velX +-500 value seems to provide a good enough result, but could be adjusted to suit your preferences.

(Note: this is using the isScrollingLeft method presented in @Nadewad's answer)

Community
  • 1
  • 1
dijipiji
  • 3,063
  • 1
  • 26
  • 21
1

THANK GOD!!! OMG, I literally plugged this into some code and it WORKED! ugh, 48-hrs straight and to think I only needed to do the perfect google search for my answer. Literally, plug and play. Thanks so much.

new code

public class CustomGallery extends Gallery {

public CustomGallery(Context context) {
    super(context);
}

public CustomGallery(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CustomGallery(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

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

@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;  
}
}

old code: just for comparison purposes

 public class CustomGallery extends Gallery {

public CustomGallery(Context context) {
    super(context);
}

public CustomGallery(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CustomGallery(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
        float distanceY) {
    //Do something specific here.
    return super.onScroll(e1, e2, distanceX, distanceY);
}
}
eeerahul
  • 1,629
  • 4
  • 27
  • 38
Newbie
  • 451
  • 4
  • 6
  • I'm glad that helped you. Actually Google has released the ViewPager class which achieves the same goal but actually does an intermediate scrolling animation while you are swiping your finger as opposed to scrolling after the swipe motion has finished. – Nadewad Mar 20 '12 at 01:52