Creating a custom ArrayAdapter for a user defined ArrayList in Android
Custom ArrayAdapters are implemented when we define a custom list. By default we can pass list items provided to us by the android team as a parameter in ArrayAdapters. But, if we want to provide a custom list with only two textviews, then the following steps must be taken:-
In this article I will be taking an example of Miwok app (taken reference from Udacity Android App Development Course) This app lists the English translation of the Miwok Language (spoken by Native Americans)
Let us first look at our Word object class, the gist of which is provided below (Comments are present in the gist for understanding)
Here a constructor is also used stated in comments, a constructor defines default values that can be provided by the calling functions the syntax of a constructor is just like function but it does not have any return type also the name of the constructor should be same as the name of class.
It is to be NOTED:- we always create private variables in a class and public methods this is because if we create public variables, any outside class can modify them accidentally, which would crash our app also since we need to access those variables we create public methods for the same, that they show the private data of the class to outside world.
Now we can use this Word object in our ArrayAdapter:-
In the above code list_item is our XML file where we have created our custom list element, a sample gist is provided below
At this point if we try to run our app it will crash because Resource ID for the arrayAdapter should be a single textview and we have passed two textviews and so we have to define a custom ArrayAdapter that takes two textviews.
First let us understand about custom arrayAdapter through another example of androidFlavors app (Link of the app:-https://github.com/udacity/ud839_CustomAdapter_Example)with two TextViews (namely versionName and versionnumber)
So we create our new adapter class named as wordAdapter class which extends ArrayAdapter<Object> class which means that wordAdapter is the subclass and ArrayAdapter is super class, since our wordAdapter class does not have a default constructor and the super class demands it we use the same constructor defined in the super class i.e. ArrayAdapter and pass the arguments (why only these are passed, it is stated in the comments in code, however it is explained below also.)
The default syntax of the array adapter is like this
notice that we have passed ‘0’ for the input resource this is because we don’t want, ArrayAdpter to inflate(or generate) the TextViews, since in our custom adapter it is handled by getView() method. Let’s discuss the arguments of the Constructor
Context:- this is of the activity which uses it
androidFlavor:- it is the object which is passed into the default constructor, usually it is the list which we have created.
After dealing with this we move further down the code we find the overrided method getView we notice it’s arguments i.e. position, convertView, parent getView method require these to run, these automatically appear when we ovverride a method through ctrl+O
Let’s first have a brief introduction of the formal arguments which appeared automatically on overriding the getView() method:-
- Position it is the list of data which can be requested like textView
- convertView is the recycledView which we want to fill.
- ParentViewGroup:- so the list item is added to this parent viewGroup
Let us have a Detailed discussion of code and how to modify the arguments in order to use our custom array adapter:-
Let’s talk about position argument:-
Moving down we see further on line 71 we see the getItem method which is defined in the superclass(i.e. ArrayAdapter) and this method returns the item in the list at the given index position and notice that the return type of this method is AndroidFlavour which is a custom Datatype class in our case it is Word.
Let’s Talk about convertView argument:-
on line 64 notice that we have assigned convertView to listView so we can easily understand that it is our listView however it is not nescessary and we can continue to use convertView if we want.
Then in line 65 we check if the view is null or not, to check if there is some existing views that we can reuse, if the view is null than in line 66 we inflate the view from the xml view which we created on page 52 a layout inflater is nothing but a method which converts the xml file to actual view object automatically, so we can perform operations on them, since we are manually inflating the view that’s why we don’t need to pass the layout resource id in the default constructor
Back to understanding this
At line 74 we passed the resource ID of the textView we created in our XML File (list_item). Since it is a textView we can use setText() method on it the only catch is on line 77 (notice we have used currentAndroidFlavour which was actually our position integer, this position integer is then used for the getter method of the custom class so that we can access it’s private variable), We have done the same process for second TextView
Note that the currentAndroidFlavour is our variable for position of objects and their values so we are getting values through it as knowing the position of the object we can set their values, keep this in mind moving on now we return the listitemview, (do remember that this listitemView is actually convertView)
On returning this we update the listItemView with the new settings from the currentAndroidFlavour (position) object, so this itemView is added as the child to the adapterView.
In my custom version of the Miwok app I have implemented the above approach in the following way:-
I hope now you can understand the above code to the fullest.
Finally we modify code in our original Activity to set our customAdapter:-