ListView is one of the most widely used widget in Android Application, it’s main usage is to show a list of child objects.

Most common scenario is using it to display a list of objects of the same type, but when you need to display more than one lists in the same Activity, you have to put them in one ListView, but writing custom Adapters to wire them up.

In this tutorial, we are going to do this in MVVM way with Android-Binding, which you can do all this work, in the layout instead of writing them in back end code. By the end of our tutorial, we would have something like this:

Source code for the tutorial is available in the project page.

Step1 – Create Project

Start Eclipse, choose File > New Project > Android Project, just like any other normal Android projects, put in package names and those stuff, and you should have a clean Project similar to the one below:

Step2 – Link Android Binding Library

Next, we need to link the Android-Binding Library. Simply right-click on the Project name (ListViewTutorial), and then choose Build Path -> Add External Archives:

After clicking that one, a file selection dialog shows up, and put in the downloaded Android-Binding.jar into it. (you may download the latest one here).

After selecting the library file, your project folder should look like this:

Now, double-click on “AndroidManifest.xml”, and choose the “Application” Tab. Click on the underlined Name, we want to add an application class associated to this project.

After clicking on it, a dialog asking you to name a new class is show up:

Put in the name, and leave everything else as-is, and click Finish.

Now, the newly created Application class appears, put in the following:

package gueei.binding.demos.listView;

import gueei.binding.Binder;
import android.app.Application;

public class ListViewTutorialApplication extends Application {
	@Override
	public void onCreate() {
		super.onCreate();
		Binder.init(this);
	}
}

Nothing much different than the default, except that we include a Binder Object, and called init(Application) to it. This is the only setup code we need to start using Android Binding.

Step 3 – Coding our View Model

We can now move on to code our View Model, which, we are going to supply the Country names to it, by continent; For simplicity reason, we prepare our names with simple String arrays, right in the Activity class:

        private static final String[] Asia = new String[]{
		"China", "Thailand", "Japan", "Korea"
	};

	private static final String[] NAmerica = new String[]{
		"U.S.A.", "Canada"
	};

	private static final String[] Europe = new String[]{
		"U.K.", "Italy", "France", "Spain", "Netherlands"
	};

We also need those string to be Public Observable, so, in the Activity class, we put:

        public ArrayListObservable AsiaList =
		new ArrayListObservable(String.class);
	public ArrayListObservable NAmericaList =
		new ArrayListObservable(String.class);
	public ArrayListObservable EuropeList =
		new ArrayListObservable(String.class);

Declaring public observable denotes that these properties are observable by the View. Since they are coming from array source, the type would be ArrayListObservable. An ArrayListObservable is very similar to the normal java.util.ArrayList, except that this is compatible to the Binding mechanism used by Android-Binding.

Lastly, in the onCreate method of our activity class, we need to specify the content View we are going to use, and also initialize the content of the above mentioned lists.

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AsiaList.setArray(Asia);
        NAmericaList.setArray(NAmerica);
        EuropeList.setArray(Europe);
        Binder.setAndBindContentView(this, R.layout.main, this);
    }

Again, for make things simpler, we double the role of the activity and ViewModel, but in practice, create a separate class for ViewModel would be much better. The Binder.setAndBindContentView tells the Binder to parse the layout xml, and also set the content view of the activity to that.

Step 4 – The Markup

Here is the basic markup we have:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:binding="http://www.gueei.com/android-binding/"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<ListView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    binding:itemSource="AsiaList"
    binding:itemTemplate="@layout/list_item"
    />
</LinearLayout>

We simply want a list view to see the content of the arrays. Note that the line xmlns:binding=… at the very beginning of the document, all Markups in Android-Binding is under that particular namespace. In the ListView, I included binding:itemSource=”AsiaList” and binding:itemTemplate=”@layout/list_item” to specify the source of items and how it looks like respectively.

Now you can try to run, and you should have the following:

Step 5 – Displaying multiple list

OK, now we can display one list, but we want to display all three lists, right?

Simplest idea is, we create three ListView in our xml, laying out one by one from top to down, and supplying them with different itemSources.

Bad news is, it cannot be done (OK, it sort of works if all the lists contains stuff less than a screen). The ListView, LinearLayout will reject to work in that way.

In usual Android programming, the work-around is to make a custom adapter (well, you always need to create this). In Android Binding, we do it in a different way.

Back to the Layout file, this time, we use the Converters mechanism in Android Binding to offload the work.

<ListView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    binding:itemSource="ADAPTER({source=AsiaList, template=@layout/list_item})"
    />

We start with bit-by-bit. Instead of putting multiple attributes, we can use ADAPTER() to specify itemSource and itemTemplate in one statement. Run the above example and nothing should change (but at least it works).

WHY? The ADAPTER() converter creates an adapter (item source and template combo), and we can put multiple adapters to it, so we can display more than one list of objects (and they can be of different types, different look).

In order to put multiple adapter, we need to STITCH() converter to do the magic:

<ListView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    binding:itemSource="STITCH(
    		ADAPTER({source=AsiaList, template=@layout/list_item}),
    		ADAPTER({source=NAmericaList, template=@layout/list_item}),
    		ADAPTER({source=EuropeList, template=@layout/list_item})
    	)"
    />

Run the code, you would have:

A single list which the data from three different lists.

Step 6 – Extra finishes

Now, we want to add a separator so that we can visually group those items. Built-in to Android Binding, there are a SECTION() converter takes the name and layout of the section:

    SECTION('DISPLAY NAME', @layout/LAYOUT)

The SECTION() (Header) Converter itself is a singleton adapter (a set with one and only one entry). So, you can chain this into the input of STITCH() Converter (stitch means stitch different adapters to make one adapter, as input for ListView itemsource).

Putting the following in the xml layout:

    <ListView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    binding:itemSource="STITCH(
    		SECTION('Asia Countries', @layout/section_name),
    		ADAPTER({source=AsiaList, template=@layout/list_item}),
    		SECTION('N. America Countries', @layout/section_name),
    		ADAPTER({source=NAmericaList, template=@layout/list_item}),
    		SECTION('Europe Countries', @layout/section_name),
    		ADAPTER({source=EuropeList, template=@layout/list_item})
    	)"
    />

yields the final product:

Final words

In the example, we are putting list of objects of the same kind, which in practice, we have ExpandableListView to do the job (we will cover how to use Android Binding on that kind of lists later). Notice since every single list can have different templates, sometimes you can have finer control on the interfaces with this approach.

About these ads