In the previous lesson, we created a string array in an XML file. This array
will be used as the sub items in our grid – the heading under the images, in
other words. In this lesson, we’ll create a Custom Adapter that receives the
sub items array. The Custom Adapter also sets the image for each item in the
grid. The Adapter is then attached to the GridView, which displays everything
for us.
Let’s now create the Custom Adapter. This is done in more or less the same
way we did previously, for the ListView app – by adding a new class and overriding
a View.
To create a new class, right-click your java folder in the Explorer
window to the left of Android Studio:
From the menu that appears, select New > Java Class. You’ll then
see the following dialogue box appear:
Type CustomAdapter for the Name. As the Superclass, type Base.
You’ll then see a popup menu. This one:
Select BaseAdapter from the list. Now put a check in the box at the
bottom for Show Select Overrides Dialog. Your New Class dialogue box
should look like this:
Click OK to see another box appear. This one:
On Windows, CTRL click to multiselect the same options as ours, in
the image above. On a Mac, COMMAND click to multiselect. So you want
to select BaseAdapter, getCount, getItem, getItemId, and getView. Click
OK to create your class. Your code should look like this in earlier
versions of Android Studio:
And this in later versions:
In later versions of Android Studio, some of the default variable names
are different. Change all the int i variables to int position.
Change View view, ViewGroup viewGroup to View convertView,
ViewGroup parent. Your code will then look like this (changes are
highlighted):
Notice that the CustomAdapter class extends BaseAdapter, which
is why we asked you to type BaseAdapter in the superclass area of the
first dialogue box. The items you multiselected are methods that are
created for you.
Now it’s time to add some images to our project.
Open an Explorer window (or Finder, if you’re on a Mac), and navigate to where
you downloaded the project files. If you haven’t yet downloaded the files for
this project, get them here:
DOWNLOAD ZIP FILE (24 Kilobytes)
Select all the animal images:
Copy them with CTRL + C (or Command + C on a Mac). Now go back to Android Studio
and select the drawable folder:
Press CTRL + V (or Command + V) to paste the images over. You’ll see this dialogue
box:
Click OK to complete the copy process. Your drawable folder will then look
like this:
We now need to point to these images with an array in our CustomAdapter code.
Just after the extends BaseAdapter line in your CustomAdapter class, add the
following to set up an array:
private Integer[ ] petImages = {
};
(Don’t forget the square brackets after Integer. ) In between the curly brackets
of the array, type R.drawable. Then type a dot. As soon as you type the dot,
you should see a popup list with all your drawable images:
Select a drawable from the list, and then type a comma. Here’s what you code
should look like:
Notice that a thumbnail of the image appears in the margins.
Hit the enter key on your keyboard to give yourself a new line. Now add the
rest of the drawables:
R.drawable.dog,
R.drawable.fish,
R.drawable.horse,
R.drawable.rabbit,
R.drawable.parrot,
R.drawable.pigeon,
R.drawable.duck
The final drawable doesn’t need a comma after it. Here’s what the coding window
will look like:
(Incidentally, if you’re wondering why the images have to go in an Integer
array rather than a String array, it’s because Android turns an image into an
ID when you put it in the drawable folder. The ID is an Integer.)
We need two variables at the top of the code. These ones:
private String[ ] imageLabels;
private LayoutInflater thisInflater;
(ALT + ENTER for any red text, or add import android.view.LayoutInflater;
to the top of your code.)
We’re going to be passing our CustomAdapter an array of headings. They will
go into a new array which we’ve called imageLabels
The LayoutInflater is used to inflate the XML file we create for a row item.
Now locate the CustomAdapter constructor in your code:
public CustomAdapter( ) {
super();
}
You can delete the super line. In between the round brackets
of CustomAdapter, pass in a Context object and a String array (a Context
just ensures that we know which of our app’s screens we’re talking about):
public CustomAdapter( Context con, String[ ] labs ) {
}
You might need to press ALT + ENTER on any red text, or add import android.content.Context;
to the top of your code.
In between the curly brackets of the constructor, set some values for the variables
at the top of your code:
this.thisInflater = LayoutInflater.from(con);
this.imageLabels = labs;
The top half of your code should look like this:
The LayoutInflator has a from method we can use. In between the round
brackets of from you need a context, which is con for us. The
labs array is stored in the imageLabels array at the top of the code.
Let’s fill out the getCount, getItem and getItemId methods. There’s only one
line for each.
The count we want is how many items are in the petImages array. Add this line
to getCount:
@Override
public int getCount() {
return petImages.length;
}
For getItem and getItemId we only need the position. Update your two methods
like this:
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
Your three methods should look like this:
The only thing left to do now, in the CustomAdapter, is write code for the
getView method.
Add this IF Statement between the curly brackets of getView;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
}
}
The variable convertView is a View object. We’ll be setting our image
and heading XML file as convertView. But we need to check if it’s null or not.
If it’s null then we can go ahead and set some values. If you don’t check for
null then you’d get too many image and headings being created, and the app could
crash. We only want to create an image and heading View if convertView
is null.
Add this between the curly brackets of the IF Statement:
convertView = thisInflater.inflate( R.layout.grid_item,
parent, false );
Our XML file with the ImageView and TextView was called grid_item. We’re
inflating this to create a View object. This then goes into the variable called
convertView. (We did all this in a previous tutorial on ListViews, so
we won’t explain the other parameters here.)
Now we have a reference to our XML file, add these two lines:
TextView textHeading = (TextView) convertView.findViewById(R.id.petHeading);
ImageView thumbnailImage = (ImageView) convertView.findViewById(R.id.petImage);
You may need to press ALT + ENTER to add the imports for ImageView and TextView.
Or add these two lines to the top of your code:
import android.widget.ImageView;
import android.widget.TextView;
All the new lines do, though, is get references to the petHeading and
petImage widgets from our grid_item XML file. We’re setting up
a TextView variable called textHeading, and a ImageView variable called
thumbnailImage.
To store something in these two variables, add the following lines:
textHeading.setText( imageLabels[position] );
thumbnailImage.setImageResource( petImages[position] );
Two understand these lines, remember that imageLabels and petImages
are both arrays. In between the square brackets of the arrays, we have the position
variable from the round brackets of getView. Whichever label or image
is at a particular position in the array gets its text or image resource set.
Finally, outside of the IF Statement, we can return convertView:
And here’s the whole of the code for your CustomAdapter:
We’re done with the CustomAdapter class. Let’s go back to MainActivity.java
and test it out.
< GridView Array |
Set Adapter >
Back to the Android Contents Page