Tuesday, April 17, 2012

Android: Create an image Viewer using ViewPager.

Hi,

This post is for those guys digging the Internet trying to find out how to create an image viewer. And I managed to do that using ViewPager.

First, you'll need to download the support package using the SDK manager.

Then, set up the project to use the library, as mentioned here. OR, if you use Eclipse, you can simply right click your project > Android Tools > Add Compatibility Library.

I'll use the project that we created in the previous tutorial to get a horizontal list of images and I'll make some modifications to get to our target.

So, the main layout will be as follows.

main.xml
 <?xml version="1.0" encoding="utf-8"?>  
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
   android:layout_width="fill_parent"  
   android:layout_height="fill_parent" >  
     
      <HorizontalScrollView android:layout_width="fill_parent"  
        android:layout_height="wrap_content">  
          
        <LinearLayout android:id="@+id/_linearLayout"  
          android:layout_width="fill_parent"  
          android:layout_height="wrap_content"  
          android:orientation="horizontal">  
            
        </LinearLayout>  
          
      </HorizontalScrollView>  
     
      <android.support.v4.view.ViewPager android:id="@+id/_viewPager"  
          android:layout_width="fill_parent"  
          android:layout_height="fill_parent"  
          android:background="#000000"  
          android:visibility="gone" />  
        
 </RelativeLayout>  

cell.xml
  <?xml version="1.0" encoding="UTF-8"?>   
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   
      android:id="@+id/linearLayout1"   
      android:layout_width="wrap_content"   
      android:layout_height="wrap_content"   
      android:orientation="vertical" >   
     
   <ImageView android:id="@+id/_image"   
       android:layout_width="wrap_content"   
       android:layout_height="wrap_content"/>   
      
   <TextView android:id="@+id/_imageName"   
       android:layout_width="wrap_content"   
       android:layout_height="wrap_content"   
       android:layout_gravity="center_horizontal"/>   
      
  </LinearLayout>   

We need to create a class that extends PagerAdapter - which is a base class that provide the adapter to populate pages inside of a ViewPager - as mentioned here.

 import android.app.Activity;  
 import android.os.Parcelable;  
 import android.support.v4.view.PagerAdapter;  
 import android.support.v4.view.ViewPager;  
 import android.view.View;  
 import android.widget.ImageView;  
   
 public class GalleryPagerAdapter extends PagerAdapter {  
   
      private Activity activity;  
      private int[] drawableIDs;  
        
      public GalleryPagerAdapter(Activity activity,int[] drawableIDs){  
             
           this.activity = activity;  
           this.drawableIDs = drawableIDs;  
      }  
        
   @Override  
   public int getCount() {  
       return drawableIDs.length;  
   }  
   
      /**  
       * Create the page for the given position. The adapter is responsible  
       * for adding the view to the container given here, although it only  
       * must ensure this is done by the time it returns from  
       * {@link #finishUpdate()}.  
       *  
       * @param container The containing View in which the page will be shown.  
       * @param position The page position to be instantiated.  
       * @return Returns an Object representing the new page. This does not  
       * need to be a View, but can be some other container of the page.  
       */  
   @Override  
   public Object instantiateItem(View collection, int position) {  
         
       ImageView imageView = new ImageView(activity);  
         
       imageView.setBackgroundResource(drawableIDs[position]);  
         
       ((ViewPager) collection).addView(imageView,0);  
         
       return imageView;  
   }  
   
      /**  
       * Remove a page for the given position. The adapter is responsible  
       * for removing the view from its container, although it only must ensure  
       * this is done by the time it returns from {@link #finishUpdate()}.  
       *  
       * @param container The containing View from which the page will be removed.  
       * @param position The page position to be removed.  
       * @param object The same object that was returned by  
       * {@link #instantiateItem(View, int)}.  
       */  
   @Override  
   public void destroyItem(View collection, int position, Object view) {  
       ((ViewPager) collection).removeView((ImageView) view);  
   }  
   
   @Override  
   public boolean isViewFromObject(View view, Object object) {  
       return view==((ImageView)object);  
   }  
   
      /**  
       * Called when the a change in the shown pages has been completed. At this  
       * point you must ensure that all of the pages have actually been added or  
       * removed from the container as appropriate.  
       * @param container The containing View which is displaying this adapter's  
       * page views.  
       */  
   @Override  
   public void finishUpdate(View arg0) {}  
     
   @Override  
   public void restoreState(Parcelable arg0, ClassLoader arg1) {}  
   
   @Override  
   public Parcelable saveState() {  
       return null;  
   }  
   
   @Override  
   public void startUpdate(View arg0) {}  
 }  

And finally, the activity.

 import android.app.Activity;  
 import android.os.Bundle;  
 import android.support.v4.view.ViewPager;  
 import android.view.View;  
 import android.view.View.OnClickListener;  
 import android.widget.ImageView;  
 import android.widget.LinearLayout;  
 import android.widget.TextView;  
   
 public class TestingActivity extends Activity {  
        
      // mainLayout is the child of the HorizontalScrollView ...  
      private LinearLayout mainLayout;  
        
      // this is an array that holds the IDs of the drawables ...  
      private int[] images = {R.drawable.dd1, R.drawable.dd2, 
      R.drawable.dd3, R.drawable.dd4, R.drawable.dd5, R.drawable.dd6, R.drawable.dd7};  
        
      private View cell;  
      private TextView text;  
        
      private ViewPager viewPager;  
        
      @Override  
      public void onBackPressed() {  
             
           if(viewPager != null && viewPager.isShown()){  
                  
                viewPager.setVisibility(View.GONE);  
           }  
           else{  
   
                super.onBackPressed();  
           }  
      }  
        
   /** Called when the activity is first created. */  
   @Override  
   public void onCreate(Bundle icicle) {  
     super.onCreate(icicle);  
       
     setContentView(R.layout.main);  
   
     viewPager = (ViewPager) findViewById(R.id._viewPager);  
       
     mainLayout = (LinearLayout) findViewById(R.id._linearLayout);  
       
     for (int i = 0; i < images.length; i++) {  
                  
          cell = getLayoutInflater().inflate(R.layout.cell, null);  
            
          final ImageView imageView = (ImageView) cell.findViewById(R.id._image);  
          imageView.setOnClickListener(new OnClickListener() {  
                       
                     @Override  
                     public void onClick(View v) {  
                            
                          viewPager.setVisibility(View.VISIBLE);  
                          viewPager.setAdapter
                          (new GalleryPagerAdapter(TestingActivity.this, images));  
                          viewPager.setCurrentItem(v.getId());  
                     }  
                });  
            
          imageView.setId(i);  
            
          text = (TextView) cell.findViewById(R.id._imageName);  
            
          imageView.setImageResource(images[i]);  
          text.setText("Image#"+(i+1));  
            
          mainLayout.addView(cell);  
       }  
   }  
 }  

That's it, don't hesitate to comment, to share your knowledge and to correct me. 

6 comments:

  1. I tried your code, but it didn't work.

    ReplyDelete
  2. thanks a lot it did work, nice and simple example :)

    ReplyDelete
  3. Hello, thanks a lot for your code, but it seems that the following function is deprecated :
    instantiateItem(View container, int position)

    http://developer.android.com/reference/android/support/v4/view/PagerAdapter.html

    ReplyDelete
  4. give space between (relative layout and xmlns:android) in main layout

    ReplyDelete
  5. If I want to load image from sd card and those images are very big, how could I implement with viewpager ?

    ReplyDelete
  6. do you have a zip file on this project?

    ReplyDelete