19 April 2013

Fast Flicking Between Images on Android

So I wanted to be able to have a simple control that supported swapping between a list of images as the user swiped/flicked their finger across the image.

My initial solution was to have a HorizontalScrollView which showed all my images in a row. This worked pretty well but I wasn't able to accurately stop to show each image on the screen as the user flicked between them. They always seemed to end up half off-screen.

After spending a few hours attempting to wrestle the scrolling events in the HorizontalScrollViewer under my control I realised that I must be doing something wrong, surely this isn't this difficult.

ViewPager

And yes, it couldn't have been simpler. More information on the android blog. But basically I ended up creating a simple PagerAdapter like so:

public class ImagePagerAdapter extends PagerAdapter 
{
 Bitmap[] _images = null;

 public ImagePagerAdapter( Bitmap[] images ) 
 {
  _images = images;
 }

 @Override
 public int getCount() 
 {
  return _images == null ? 0 : _images.length;
 }

 @Override
 public boolean isViewFromObject(View view, Object object) 
 {
  return view == ((ImageView)object);
 }
 
 @Override
    public Object instantiateItem(ViewGroup container, int position) 
 {
  ImageView img = null;
  
  if( position >= 0 && position < _images.length )
  {
   final Bitmap bmp = _images[position];
   
   img = new ImageView(container.getContext());
   img.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
   img.setImageBitmap(bmp);
   img.setScaleType(ImageView.ScaleType.CENTER_CROP);
   ((ViewPager)container).addView(img, 0);
  }
  
  return img;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) 
    {
     ((ViewPager)container).removeView((ImageView)object);
    }

}

Then in my Activity/Fragment class it was a simple matter of just assigning the adapter to my pager and that is it!

ImagePagerAdapter adapter = new ImagePagerAdapter(bitmaps);
((ViewPager)v.findViewById(R.id.fragment_bird_banner_viewpager)).setAdapter(adapter);

Lesson: If things that you feel should be basic are becoming too complicated and taking too much time. You're probably doing them wrong. Step back and search/read a little bit. :)