If we want more control over the parts of the data to be rendered and how the data is rendered for each item, we can use a different adapter and different item templates.
List views allow us to entirely customize each item view through item templates. Android has a few predefined templates that we can use:
ArrayAdapter<T>
type and a simple string collection:var adapter = new ArrayAdapter<string>( this, Android.Resource.Layout.SimpleListItem1, data);
JavaDictionary<string, object>
objects:var data = new JavaList<IDictionary<string, object>>();
Add()
method:data.Add(new JavaDictionary<string, object> { { "name", "Bruce Banner" }, { "status", "Bruce Banner feels like SMASHING!" } });
SimpleAdapter
type, which allows us to map a particular key in the dictionary to a view in the item:var adapter = new SimpleAdapter( this, data, Android.Resource.Layout.SimpleListItem1, new[] { "name" }, new[] { Android.Resource.Id.Text1 });
SimpleAdapter
type also allows us to map multiple keys to multiple views in each item; to do this, we use a different item resource:SimpleAdapter adapter = new SimpleAdapter( this, data, Android.Resource.Layout.SimpleListItem2, new[] { "name", "status" }, new[] { Android.Resource.Id.Text1, Android.Resource.Id.Text2 });
var adapter = new SimpleAdapter(
this, data, Android.Resource.Layout.SimpleListItemChecked,
new[] { "name" }, new[] { Android.Resource.Id.Text1 });
ChoiceMode
is either Multiple
or Single
:listView.ChoiceMode = ChoiceMode.Single;
Passing collections between .NET and Java is slightly more complex than it appears. When we pass a collection to Java, only a copy of the collection is passed. This means that, if the collection is modified by some object on the Java side, the changes are not reflected on the .NET side. Xamarin.Android has a way of addressing this problem by providing various Java collections, such as JavaList
and JavaDictionary
. These collections are simple wrappers to the underlying Java collections.
There are advantages of using both types of collections. If we use the .NET collections, the objects exist in .NET and a copy is passed to Java. This copy is not linked to the original, and is managed separately by both the .NET and Java garbage collectors. The downside is that the .NET collection is not updated when the Java collection is; however, this method is not used very often.
If we use the Java collections, the collection is created in Java and a wrapper is created in .NET. This allows a collection to be updated if the other one is. However, every time we wish to access the items or update the collection, the item is passed to the underlying Java collection and back again.
The SimpleAdapter
type allows us to easily map a slightly more complex datatype to a structured view. When constructing the adapter, we provide the data along with two arrays that are used to map an item property to a view.
The data is a collection of dictionaries, with each dictionary representing an item from the list. The dictionary is used to label a value. Each of the dictionaries should contain the same set of keys, as these represent the attributes of the data.
The last two parameters in the constructor, two arrays, are used together to map a dictionary key to a view ID. The first array contains the collection of dictionary keys, and the second contains a collection of IDs. The size of the arrays should be the same as each item corresponds directly to the item in the same position in the other array.
The adapter iterates through the items in the arrays and, after obtaining the value from the dictionary using the key in the first array, it updates the corresponding view using the ID in the second array.
As the SimpleArray
type takes a resource ID for the item template as a parameter, we can create our own item layouts and use those IDs instead of the Android ones. If we need to have even more control over the adapter, we can create our own adapter by inheriting from the BaseAdapter
type.