Many apps have user interfaces that are composed of lists. Some of these lists are static and unchanging. Some are updated with information from a server. Some are directly editable by the user. Some of them can be interacted with to launch other screens. If you look at any mobile app, there is probably going to be a fair amount of scrollable lists.

In Android, a list is built using a ListView. This is a more complex view than we've learnt about in the past. So, we're going to take it in pieces. We will start with a simplified version that introduces us to the main concepts and components. When we've learnt some more programming concepts, like inheritance, we will cycle back to ListView and expand our understanding of how to build much more complex lists. So, we will be taking some shortcuts for the purpose of this lesson. When looking up other ListView resources online, you may see a very different way of doing some of these things. We will get to that point over the next two weeks, so do not be alarmed or confused.

Let's start with some concepts. A ListView is a View, which displays a vertically scrolling list of items. This is the user interface. Our actual data is stored in an ArrayList. We need a way to connect these two pieces. This is where an adapter is used, to adapt the data into views that can be shown on screen. Specifically, we will be using an ArrayAdapter, which connects an ArrayList to a ListView. This adapter is in charge of converting our data into views.


A ListView is just a vertical collection of smaller views, or cells. These small views can be defined in a layout file. The adapter takes each item in our ArrayList, turns it into a cell, and inserts it into the ListView.

First, let's start with the ListView. Open up your layout file (activity_main.xml) and insert this into your layout:

<ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

As always, you can have different layout attributes from this, if your ListView is a different size, or is placed relative to another view. The important bit is the ListView, and that it has an ID.

Let's head back to MainActivity. We need an ArrayList with data in it. Let's make a String ArrayList:

ArrayList<String> list;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    list = new ArrayList();
    list.add("a");
    list.add("b");
    list.add("c");
}

Notice that I am declaring the list as an instance variable (declared in MainActivity, outside of a function). This is because I might want to later interact with list from another function.

So, we have a ListView, and we have an ArrayList. We now need an ArrayAdapter to connect the two. Let's start with declaration:

ArrayList<String> list;
ArrayAdapter<String> itemsAdapter;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    list = new ArrayList();
    list.add("a");
    list.add("b");
    list.add("c");

    itemsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
}

Again, we have declared the itemsAdapter as an instance variable. Let's look at the ArrayAdapter constructor. The constructor takes 3 arguments. The first is the context, which is the current activity. The second is the layout for each item. This can be a custom layout, and we will look at doing that in a future lesson. In this case, we are using one of the built in layouts in the Android SDK, called "simple list item 1". You can take a look at this layout here: https://github.com/android/platform\_frameworks\_base/blob/master/core/res/res/layout/simple\_list\_item\_1.xml. The third argument is the list itself.

That takes care of one half of what we want: the connection between the adapter and the list. Let's now do the second half:

ArrayList<String> list;
ArrayAdapter<String> itemsAdapter;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    list = new ArrayList();
    list.add("a");
    list.add("b");
    list.add("c");

    itemsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);

    ListView listView = (ListView) findViewById(R.id.list);
    listView.setAdapter(itemsAdapter);
}

The first line gets a hold of our ListView like we've seen. The second like tells the listView to use our adapter. This means that whenever the ListView needs to fill up a view, it will come to itemsAdapter to figure out what needs to go in that view.

Run the app! You should have a ListView with the 3 items populated in it. If the ListView is too small to hold the items, it should be scrollable as well.


Let's see how we can update the list and trigger an update in the UI. First, add a button to your user interface and create an onClick for us to code in. We are going to add an element to the list every time the button is clicked. Now write this:

public void buttonClick(View v) {
    list.add("new row");
    itemsAdapter.notifyDataSetChanged();
}

The first line adds a new string to the list. But this is not enough; we need to let the adapter know that data has changed. So the second line calls the notifyDataSetChanged method. Remember to call this method every time you change the underlying ArrayList. Otherwise, there will be inconsistencies between what is on the screen, and the array of information. The adapter is the middleman, and so needs to be notified when the data source changes.


Try: Add a way for users to input what the name of the new row should be. Make it user friendly; clear the EditText when they click the button and a row is created.

results matching ""

    No results matching ""