Building an image gallery/slider app

Create a new project in Android Studio called Image Pager. Use the Basic Activity template and leave the remainder of the settings at their defaults.

The images are located in the download bundle in the Chapter 25/Image Pager/drawable folder. The following diagram shows them in Windows Explorer:

Building an image gallery/slider app

Add the images to the drawable folder in the project explorer or, of course, you could add more interesting images, perhaps some photos you have taken.

Implementing the layout

For a simple image paging app, we use the PagerAdapter class. We can think of this as being like RecyclerApater, but for images, as it will handle the display of an array of images in a ViewPager widget. This is much like how RecyclerAdapter handles the display of the content of an ArrayList in a ListView. All we need to do is override the appropriate methods.

To implement an image gallery with PagerAdapter, we first need a ViewPager in our main layout. So you can see precisely what is required here is the actual XML code for activity_main.xml. Edit layout_main.xml to look exactly like this:

<RelativeLayout xmlns:android=
   "http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/pager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

The slightly unusually named class, androidx.ViewPager.widget.ViewPager, is the class that makes this functionality available in Android versions that were released prior to ViewPager.

Next, a bit like we needed a layout to represent a list item, we need a layout to represent an item, in this case an image, in our ViewPager. Create a new layout file in the usual way, and call it pager_item.xml. It will have a single ImageView with an id of imageView.

Use the visual designer to achieve this or copy the following XML into pager_item.xml:

<RelativeLayout xmlns:android=
   "http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/pager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

Now we can make a start on our PagerAdapter.

Coding the PagerAdapter class

Next, we need to extend PagerAdapter to handle images. Create a new class called ImagePagerAdapter and make it extend PagerAdapter.

Add the following imports to the top of the ImagePagerAdapter class. We normally rely on using the shortcut Alt + Enter to add imports. We are doing things slightly differently this time because there are some very similarly named classes that will not suit our objectives.

Add the following imports to the ImagePagerAdapter class:

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;

Here is the class declaration with the extends... code added, as well as a couple of member variables. These variables are a Context object that we will use shortly and an int array called images. The reason for having an int array for images is because we will store int identifiers for images. We will see how this works in a few code blocks time. The last member variable is a LayoutInflater, which you can probably guess will be used to inflate each of the instances of pager_item.xml.

Extend PagerAdapter and add the member variables we have just discussed:

public class ImagePagerAdapter extends PagerAdapter {

    Context context;

    int[] images;
    LayoutInflater inflater;	
}

Now we need a constructor that sets up ImagerPagerAdapter by receiving the Context from MainActivity, as well as the int array for the images, and initializing the member variables with them.

Add the highlighted constructor method to the ImagePagerAdapter class;

public ImagePagerAdapter(
   Context context,  int[] images) {
   
   this.context = context;
   this.images = images;
}

Now, we must override the required methods of PagerAdapter. Immediately after the previous code, add the overridden getCount method, which simply returns the number of image IDs in the array. This method is used internally by the class:

@Override
public int getCount() {

   return images.length;
}

Now we must override the isViewFromObject method that just returns a Boolean, dependent upon whether the current View is the same or associated with the current Object as passed in as a parameter. Again, this is a method that is used internally by the class. Immediately after the previous code, add this overridden method:

@Override
public boolean isViewFromObject(View view, Object object) {
   return view == object;
}

Now we must override the instantiateItem method and this is where we do most of the work that concerns us. First, we declare a new ImageView object, and then we initialize our LayoutInflater member. Next, we use the LayoutInflater to declare and initialize a new View from our pager_item.xml layout file.

After this, we get a reference to the ImageView inside the pager_item.xml layout. We can now add the appropriate image as the content of the ImageView based on the position parameter of the instantiateItem method and the appropriate ID from the images array.

Finally, we add the layout to the PagerAdapter with addView and return from the method.

Now add the method we have just discussed:

@Override
public Object instantiateItem(
   ViewGroup container, int position) {

   ImageView image;

   Inflater = (LayoutInflater) 
         context.getSystemService(
         Context.LAYOUT_INFLATER_SERVICE);
         
   View itemView = inflater.inflate(
         R.layout.pager_item, container,false);

   // get reference to imageView in pager_item layout
   image = (ImageView) 
         itemView.findViewById(R.id.imageView);

   // Set an image to the ImageView
   image.setImageResource(images[position]);

   // Add pager_item layout as the current page to the ViewPager
   ((ViewPager) container).addView(itemView);

   return itemView;
}

The last method we must override is destroyItem, which the class can call when it needs to remove an appropriate item based on the value of the position parameter.

Add the destroyItem method after the previous code and before the closing curly brace of the ImagePagerAdapter class:

@Override
public void destroyItem(ViewGroup container, 
   int position, 
   Object object) {
   
   // Remove pager_item layout from ViewPager
   ((ViewPager) container)
         .removeView((RelativeLayout) object);
}

As we saw when coding ImagePagerAdapter, there is very little to it. It is just a case of properly implementing the overridden methods that the ImagePagerAdapter class uses to help make things work smoothly behind the scenes.

Now we can code the MainActivity class that will use the ImagePagerAdapter.

Coding the MainActivity class

Finally, we can code our MainActivity class. As with the ImagePagerAdapter class, for clarity, add the following import statements manually to the MainActivity.java class before the class declaration as shown in the following snippet:

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;

We need a few member variables. Unsurprisingly, we need a ViewPager, which will be used to get a reference to the ViewPager in our layout, as well as an ImagePagerAdapter reference for the class we have just coded. We also need an int array to hold an array of image ids.

Adapt the MainActivity class to be as follows:

public class MainActivity extends AppCompatActivity {

   ViewPager viewPager;
   PagerAdapter adapter;

   int[] images;

   @Override
   public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          ...

All the rest of the code goes in onCreate. We initialize our int array with each of the images that we added to the drawable-xhdpi folder.

We initialize the ViewPager in the usual way with the findViewByID method. We also initialize our ImagePagerAdapter by passing in a reference of MainActivity and the images array, as required by the constructor that we coded previously. Finally, we bind the adapter to the pager with setAdapter.

Code onCreate to look just like this following code:

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);

   setContentView(R.layout.activity_main);

   // Grab all the images and stuff them in our array
   images = new int[] { R.drawable.image1,
                R.drawable.image2,
                R.drawable.image3,
                R.drawable.image4,
                R.drawable.image5,
                R.drawable.image6 };

   // get a reference to the ViewPager in the layout
   viewPager = (ViewPager) findViewById(R.id.pager);

   // Initialize our adapter
   adapter = new 
          ImagePagerAdapter(MainActivity.this, images);

   // Binds the Adapter to the ViewPager
   viewPager.setAdapter(adapter);

}

Now we are ready to run the app.

Running the gallery app

Here we can see the first image from our int array:

Running the gallery app

Swipe a little right and left to see the pleasing manner in which the images transition smoothly:

Running the gallery app

Now we will build an app with almost identical functionality, except that each page in the pager will be a Fragment, which could have any or all of the functionality a regular Fragment can have because they are regular Fragments.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.223.123