Adapting to Custom Adapters
If you just started creating apps in Android Studio, you undoubtedly used ListViews in one or more of your activities. When I began programming for Android, one of the most interesting concepts to learn was creating a custom adapter for the ListView. The custom adapter can completely change your user interface, allowing the ListView to relay more information to the user, as well as making it visually interesting.
In this article, we are going to create a simple list view using a basic adapter. Once that is completed, we are going to replace our basic adapter with a custom adapter.
THE SIMPLE ADAPTER
To keep things from getting too complicated, we are firsts going to display the data in an ArrayList in a simple view.
- Create a basic Android App, choosing an Empty Activity and the defaults
- Add a ListView with the id myListView to activity_main.xml
<ListView
android:id="@+id/myListView"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
3. In MainActivity.java, add the following to the onCreate() method to get reference to the list view you defined in the xml file
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//A. Add this to get reference to the list view
ListView myListView = (ListView)findViewById(R.id.myListView);
}
4. In MainActivity.java, add the following to the onCreate() method to create and populate the ArrayList that will be displayed by the ListView. Remember, the ListView is basically a View that allows you to see some underlying data whether it be from a database or from some other source. In this example, we are going to use an ArrayList to keep things simple.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//A. Add this to get reference to the list view
ListView myListView = (ListView)findViewById(R.id.myListView);
//B. create data in an array list to populate the listview
ArrayList<String>theData = new ArrayList<>();
theData.add("Item1");
theData.add("Item2");
theData.add("Item3");
theData.add("Item4");
theData.add("Item5");
theData.add("Item6");
theData.add("Item7");
theData.add("Item8");
}
5. Finally, in MainActivity.java, add the code to create an ArrayAdapter and link it to the ListView
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//A. Add this to get reference to the list view
ListView myListView = (ListView)findViewById(R.id.myListView);
//B. create data in an array list to populate the listview
ArrayList<String>theData = new ArrayList<>();
theData.add("Item1");
theData.add("Item2");
theData.add("Item3");
theData.add("Item4");
theData.add("Item5");
theData.add("Item6");
theData.add("Item7");
theData.add("Item8");
//C.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, theData);
//D.
myListView.setAdapter(adapter);
}Congratulations, you just created a ListView that displays the data in an ArrayList using an ArrayAdapter. Run the program and take it look! You should see a list with texts on each line. Cool, but not that interesting to look at.
THE CUSTOM ADAPTER
To use a custom adapter, all we have to do is replace the line labeled C in the above code with our custom adapter,but first, we have to create our custom adapter.
The first step in creating a custom adapter, is creating the layout that will be used by each line of the list. Instead of showing just one line of text per line, our adapter is going to display a line of text and an image.
- Create a new layout resource file called custom_list_item.xml and add the following into the newly created file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/title_tf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/image_tf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"/>
</LinearLayout>
The xml file above represents each line of the ListView. According to the above code, each line of the list view will have some text and an image view.
2. Next create a new Java class called CustomListViewAdapter. This class is going to extend the ArrayAdapter. This allows our new class to have the functionality of the ArrayAdapter, but because we extend the class, we also have the ability to add changes in our version.
public class CustomListViewAdapter extends ArrayAdapter<String> {
//I. This member variable will reference the ArrayList that comes in
ArrayList<String> mTheDataArrayList;
public CustomListViewAdapter(Context context, ArrayList<String>theDataArrayList) {
super(context, -1);
mTheDataArrayList = theDataArrayList;
}
//II. getView returns an inflated version of our xml layout
@Override
public View getView(int position, View convertView, ViewGroup parent) {
String theString = mTheDataArrayList.get(position);
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View custom_list_item_view = inflater.inflate(R.layout.custom_list_item,parent,false);
//III. Get reference to the text view created in the xml layout
TextView textView = (TextView)custom_list_item_view.findViewById(R.id.title_tf);
textView.setText(theString);
//IV. Get reference to the image view created in the xml layout
ImageView imageView = (ImageView)custom_list_item_view.findViewById(R.id.image_tf);
//set the image to be displayed in the imageView
if(position%2==0)
imageView.setImageResource(R.drawable.sad_face);
else
imageView.setImageResource(R.drawable.smiley_face);
return custom_list_item_view;
}
//V. return the count
@Override
public int getCount() {
return mTheDataArrayList.size();
}
}
Note: The above example displays images saved in the drawable folder. You can use any images you want instead.
There are four main takeaways from the code above:
- We have a member variable ArrayList<String> that is of the same type of the underlying data of the ListView. This member variable will actually reference the data previously created.
- The ListView “speaks” to the adapter, and the ListView calls getCount() because it wants to know how big the underlying data is. Our custom adapter returns the number of items in the underlying data.
- The second question ListView “asks” the adapter is for a View to be displayed on each line of the list. Think of it as if the ListView says, “Hey, what do you want me to show for the data in the ArrayList at a certain position?” See the parameters to the getView() method above.
- Finally, the Adapter responds by creating a view and populating it with the information from the underlying display. That view is returned to the ListView to be displayed.
The very last step is going back to our MainActivity.java class and changing the instantiation of the ArrayAdapter to our new class CustomListViewAdapter.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//A. Add this to get reference to the list view
ListView myListView = (ListView)findViewById(R.id.myListView);
//B. create data in an array list to populate the listview
ArrayList<String>theData = new ArrayList<>();
theData.add("Item1");
theData.add("Item2");
theData.add("Item3");
theData.add("Item4");
theData.add("Item5");
theData.add("Item6");
theData.add("Item7");
theData.add("Item8");
//C.
//ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
// android.R.layout.simple_list_item_1, android.R.id.text1, theData);
CustomListViewAdapter adapter = new CustomListViewAdapter(MainActivity.this,theData);
//D.
myListView.setAdapter(adapter);
}And there you have it, your very own custom adapter!