Android User Interface Design: Building a ListView Application

Android User Interface Design: Building a ListView Application

Tutorial Details
  • Technology: Eclipse + Android SDK
  • Difficulty: Intermediate
  • Estimated Completion Time: 60-90 Minutes
This entry is part 9 of 21 in the series Android User Interface Design

The ListView is one of the most useful view controls available on the Android platform for the display of variable amounts of data. In this Mobiletuts+ tutorial, we’ll show you how to use a ListView to browse a list of articles!

Over the last several months, you’ve seen many tutorials covering various layout controls. You’ll use several of these in conjunction with a ListView in today’s tutorial. The application itself will be very simple: it will display a list of article titles which, when clicked, display the article’s content. The pacing of this tutorial is going to be faster than some of our beginning tutorials; you may have to review some of our other tutorials on this site or even in the Android API reference if you are unfamiliar with basic Android controls or concepts. The final open-source code is available for download on Google code hosting.

Step 0: Creating a Project

Create a new Android project in Eclipse. We’ve named ours MT-List, with a starting activity named TutListActivity. This Activity must extend the ListActivity class, which is a special Activity class that helps manage a ListView control. We’re using a target API Level of 10 (Android 2.3.3).

Step 1: Designing the List Screen

Actually, there is very little design work here. A ListView control consists of repeating items, each with the same layout (a template for an item). We want to display a list of article titles. Each title will be a single item in the ListView. Therefore, the template for each list item need only have a TextView control. Add a new layout resource file to your project named list_item.xml which represents the template layout for each item in the list. In this case, it should look like this:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="24dp"
    android:padding="6dp" />

The text size plus the padding attributes ensure that each list item is a big enough touch target for the average human finger on an average sized screen..

Step 2: Populating the ListView with Data

ListView controls are design to load data from a data source. An adapter can be used to read from a database, array, or other data source. We’ll use an array implementation for this application. Later on, you could always replace the array with some sort of live data source. Create two string-array resources in your project (you can add them to strings.xml or a separate arrays.xml file, your choice). Name one array “tut_titles” and the other “tut_links”. Fill in the arrays with valid titles and valid URLs from the Mobiletuts+ website. Here are our arrays:

<string-array name="tut_titles">
    <item>Design &amp; Build a 1980s iOS Phone App: Design Comp Slicing</item>
    <item>Best of Tuts+ in February 2011</item>
    <item>Create a Brick Breaker Game with the Corona SDK: Game Controls</item>
    <item>Exporting Graphics for Mobile Apps: PNG or JPEG?</item>
    <item>Android Tablet Design</item>
    <item>Build a Titanium Mobile Pizza Ordering App: Order Form Setup</item>
    <item>Create a Brick Breaker Game with the Corona SDK: Application Setup</item>
    <item>Android Tablet Virtual Device Configurations</item>
    <item>Build a Titanium Mobile Pizza Ordering App: Topping Selection</item>
    <item>Design &amp; Build a 1980s iOS Phone App: Interface Builder Setup</item>
</string-array>
<string-array name="tut_links">
    <item>http://mobile.tutsplus.com/tutorials/mobile-design-tutorials/80s-phone-app-slicing/</item>
    <item>http://mobile.tutsplus.com/articles/news/best-of-tuts-in-february-2011/</item>
    <item>http://mobile.tutsplus.com/tutorials/corona/create-a-brick-breaker-game-with-the-corona-sdk-game-controls/</item>
    <item>http://mobile.tutsplus.com/tutorials/mobile-design-tutorials/mobile-design_png-or-jpg/</item>
    <item>http://mobile.tutsplus.com/tutorials/android/android-tablet-design/</item>
    <item>http://mobile.tutsplus.com/tutorials/appcelerator/build-a-titanium-mobile-pizza-ordering-app-order-form-setup/</item>
    <item>http://mobile.tutsplus.com/tutorials/corona/corona-sdk_brick-breaker/</item>
    <item>http://mobile.tutsplus.com/tutorials/android/android-sdk_tablet_virtual-device-configuration/</item>
    <item>http://mobile.tutsplus.com/tutorials/appcelerator/pizza-ordering-app-part-2/</item>
    <item>http://mobile.tutsplus.com/tutorials/iphone/1980s-phone-app_interface-builder-setup/</item>
</string-array>

This data is, of course, static. In some cases, using static data can make sense for a ListView. Using a string array resource for these cases turns out to be very easy and convenient. Just make sure the ordering of the titles and their links is identical, such that the array indices match.

Step 3: Adapting the Data to the ListView

Now that the application has data, it’s time to display it. Back in TutListActivity.java, modify the onCreate() method to use the setListAdapter() method to load up the data. Unlike regular activities, a ListActivity does not need the use of setContentView() for cases where the entire activity is just a ListView. When done, your entire ListActivity will now look like this:

public class TutListActivity extends ListActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(ArrayAdapter.createFromResource(getApplicationContext(),
                R.array.tut_titles, R.layout.list_item));
    }
}

At this point, you can run the application. You’ll now see a ListView with all of the titles of the tutorials. Scrolling up and down works as expected. However, clicking a title does not do anything yet.

Android Listview Figure 1

Step 4: Handling ListView Item Clicks

Handling clicks on items within a ListView is done in a similar way to other View objects: by using a listener. In this case, we’re interested in the OnTimeClickListener. You might have noticed that we haven’t once dealt with the ListView object directly. Now is the time. In a ListActivity, simply make a call to the getListView() method to retrieve the ListView and then call the setOnItemClickListener() method and implement it all in one go:

getListView().setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
        // TBD
    }
});

The onItemClick() method will be called each time the user clicks on a particular item within the ListView. Conveniently, it passes in several useful parameters, one of which we’ll need for launching the viewer activity. Wait, what viewer activity?

Step 5: Creating the Viewer Activity

Good question. Let’s create a viewer activity now! This activity will be used to display the tutorial contents to the user. Create a new class by extending Activity and name it TutViewerActivity.java. Create a layout resource file for it that has exactly one item: a WebView control. The layout file should look like this:

<?xml version="1.0" encoding="utf-8"?>
<WebView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/tutView">
</WebView>

Within the onCreate() method of the TutViewerActivity class, call the setContentView() method and pass in this layout. Finally, don’t forget to add the activity to your AndroidManifest.xml file.

Step 6: Launching the Details Activity

Switch your attention back to TutListActivity for a moment. Let’s look at what we need to do to launch the viewer Activity with the appropriate article link. Inside the onItemClick() method, the position of the item that was clicked is passed in as an int type value. This is exactly what we need for accessing the array of article links.

The string values within the links array are URLs. A convenient way to pass a URL to another activity is by adding a Uri to the Intent via the setData() method. Here is the final onItemClick() implementation which starts the viewer activity, passing in the appropriate URL:

@Override
public void onItemClick(AdapterView<?> parent, View view,
        int position, long id) {
    String content = links[position];
    Intent showContent = new Intent(getApplicationContext(),
            TutViewerActivity.class);
    showContent.setData(Uri.parse(content));
    startActivity(showContent);
}

If you just paste that at the end of the onCreate() method, you’ll notice that the links variable isn’t defined yet. Since it’ll be used within the OnItemClickListener class, the variable must be a final value, like so:

final String[] links = getResources().getStringArray(R.array.tut_links);

This line must be placed before the OnItemClickListener definition. Yes, you could have made it a member variable without being final. For a more complex case, that might even be necessary. But, in this case, we can actually keep all code within the method.

At this point, if you run the application, you’ll get a blank white viewer screen. The activity is launched correctly, but we need to go wire up the viewer activity to load the URL in the WebView control.

Step 7: Loading the URL

Turn your attention back to TutViewerActivity.java. After the setContentView() call, add code to retrieve the Uri from the passed in Intent and convert it to a String variable. Then add a call to the loadUrl() method of the WebView class. The entire TutViewerActivity class will now look like this:

public class TutViewerActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tut_view);
        Intent launchingIntent = getIntent();
        String content = launchingIntent.getData().toString();
        WebView viewer = (WebView) findViewById(R.id.tutView);
        viewer.loadUrl(content);
    }
}

Run the application now. Does it work? Not quite yet! One final detail: you need to add the Internet permission to the AndroidManifest.xml file. Now run the application. You’ll now see that the implementation works:

Android Listview Figure 2

Step 8: Refining the Experience (Optional)

The experience, as-is, works. A ListView shows all of the article titles, a user can click on a specific list item and be redirected to an activity with a WebView to show the appropriate URL. Some refinements that you might consider making to this basic implementation include:

  • Setting the initial zoom of the browser view to be zoomed out further
  • Configuring the WebView to have more control over the browsing experience
  • Loading the list of tutorials dynamically, instead of via a static array
  • Adding fancy visual attributes to the ListView
  • Making better use of larger screens (i.e. fragments)
  • Adding supplementary information to the ListView items: subtitles, difficulty levels, icons, “read” indicators, favorites, etc.

Other Android tutorials on this site will teach you how to perform many of these optional features. Others you may have to discover yourself — or ask about in the comments!

Conclusion

The ListView widget is a fast way to organize data in a list format on the screen. We have only scratched the surface of the ListView control in this tutorial. However, you have learned the basics of: creating list items, working with data adapters, and handling list item clicks.

About the Authors

Mobile developers Lauren Darcey and Shane Conder have coauthored several books on Android development: an in-depth programming book entitled Android Wireless Application Development and Sams Teach Yourself Android Application Development in 24 Hours. When not writing, they spend their time developing mobile software at their company and providing consulting services. They can be reached at via email to androidwirelessdev+mt@gmail.com, via their blog at androidbook.blogspot.com, and on Twitter @androidwireless.

Need More Help Writing Android Apps? Check out our Latest Books and Resources!

Buy Android Wireless Application Development, 2nd Edition  Buy Sam's Teach Yourself Android Application Development in 24 Hours  Mamlambo code at Code Canyon

Series Navigation«Android User Interface Design: Frame LayoutsAndroid User Interface Design: Working With Fragments»

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Android

    Nice example, to get through with the listview, like this if we need to check with custom listview of need to go through with multiple listview in a activity means we can go with this link http://android-codes-examples.blogspot.com/2011/03/multiple-listview-and-custom-listview.html

  • Chaos

    Setting up the tut_view.xml is never covered. Searching the page reveals that the first time tut_view is mentioned is inline with the setContentView(R.layout.tut_view).

    Could you update the tutorial to illustrate how tut_view.xml should look?

    Thanks. Great tutorial, otherwise. Trying to do this and move onto the Fragments.

    • Chaos

      Nevermind…there is a difference between layout and id, isn’t there?

      Yeah. Great tutorial…get the pupil thinking and not just doing.

  • Himo

    Design a mobile application which will have a main ListView interface ( for the main activity of the app) with 3 items which when selecting the item with a given index will:
    0) give the user an option to give some integer numbers ( for end let the user enter -1) by an edittext box and store those in an array, then one button Max which on click will then find the maximum of those numbers stored in the array and show the result within a textbox.
    1) give the user an option to give some integer numbers ( for end let the user enter -1) by an edittext box and store those in an array, then one button Min which on click will then find the minimum of those numbers stored in the array and show the result within a textbox.
    Note here, you have to define your own adapter which will show different icon on the list item ( for max).

    CAN ANYONE HELP ME WITH THESE

    • http://eazyigz.wordpress.com Igor G.

      Why do you need 3 items in the ListView for this??

  • fennou

    i have followed the same steps as you but , it dosen’t work :( the emulatore displays this message ” the application NAME_OF_APPLICATION ( process PACKAGE ) has stopped unexpectedly . please try again “

  • http://www.developerscode.com/ Developers

    Gr8 Tuts…Thanks for sharing

  • http://squirrelsewer.blogspot.com Squirrels Ewer

    Typo on step 4 – “OnTimeClickListener”

    • gamini

      Hi

      I could not understand Step 4 ? What is the correct

  • sathya

    Thanks ..

    Nice tutorial.. helped a lot

  • http://www.madmax25.com/ Max

    I was having issue on step #6 with the StartActivity method failing and found this link:
    http://androidforums.com/application-development/103343-startactivity-crashing.html

    Thanks to markb; if you have this problem, my missing link was the Activity reference in the AndroidManifest.xml file:

    I added the test_viewer string as well in res/values/strings.xml:
    UITestViewer

    Thank you Shane and Lauren; this was a great and very relevant tutorial.

    • Martin

      Because I’m a total Android noob, it’d took a little work (which is good) to figure out what the missing link was… For those who are noobish, here is the what was missing:

      I placed it immediately following the line (belongs to <activity android:name=".TutListActivity").

      HTH

      • Remus

        where did you placed it more exactly

      • http://eazyigz.wordpress.com Igor G.

        You can put it at the bottom in the section like this:

  • Maxim

    I created a listview application and everything works fine, the problem is, that I can’t figure out how to keep the selected state of the item I click on: In other words when I press on it it turns orange, displays the list item, and the orange goes away, how do I make stay orange?

    Thanks,
    I hope you understand my explanation

  • Guest

    > setListAdapter(ArrayAdapter.createFromResource(getApplicationContext(),
    > R.array.tut_titles, R.layout.list_item));

    Ugh.

    Nothing can work without that list_item you forgot to include.

    • http://eazyigz.wordpress.com Igor G.

      He didn’t forget to include list_item.xml. It is there in the tutorial.

  • http://mobile.tutsplus.com/tutorials/android/android-listview/ Judes

    good one to beginners

  • gamini

    Hi

    Education complex

    I work step by step, but did not succeeded

    3 Days In the implementation of the project but does not benefit

    We want the names all files

    For example
    list_item.xml & tutView & a what

    Note: main.xml & strings.xml “I did not work out anything”

    “Could you update the tutorial to illustrate”

    =======================================================
    Look at this :

    TutListActivity.java

    import android.app.ListActivity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.ArrayAdapter;

    public class TutListActivity extends ListActivity {

    final String[] links = getResources().getStringArray(R.array.tut_links);
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setListAdapter(ArrayAdapter.createFromResource(getApplicationContext(),
    R.array.tut_titles, R.layout.list_item));

    getListView().setOnItemClickListener(new OnItemClickListener() {

    public void onItemClick(AdapterView parent, View view,
    int position, long id){
    String content = links[position];
    Intent showContent = new Intent(getApplicationContext(),
    TutViewerActivity.class);
    showContent.setData(Uri.parse(content));
    startActivity(showContent);

    }});

    }};
    =======================================================

    TutViewerActivity.java

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.webkit.WebView;

    public class TutViewerActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.tut_view);

    Intent launchingIntent = getIntent();
    String content = launchingIntent.getData().toString();

    WebView viewer = (WebView) findViewById(R.id.tutView);
    viewer.loadUrl(content);
    }

    }
    ========================================================

    list_item.xml

    ======================================================

    tut_view.xml

    ===================================================

    arrays.xml

    Design & Build a 1980s iOS Phone App: Design Comp Slicing
    Best of Tuts+ in February 2011
    Create a Brick Breaker Game with the Corona SDK: Game Controls
    Exporting Graphics for Mobile Apps: PNG or JPEG?
    Android Tablet Design
    Build a Titanium Mobile Pizza Ordering App: Order Form Setup
    Create a Brick Breaker Game with the Corona SDK: Application Setup
    Android Tablet Virtual Device Configurations
    Build a Titanium Mobile Pizza Ordering App: Topping Selection
    Design & Build a 1980s iOS Phone App: Interface Builder Setup

    http://mobile.tutsplus.com/tutorials/mobile-design-tutorials/80s-phone-app-slicing/
    http://mobile.tutsplus.com/articles/news/best-of-tuts-in-february-2011/
    http://mobile.tutsplus.com/tutorials/corona/create-a-brick-breaker-game-with-the-corona-sdk-game-controls/
    http://mobile.tutsplus.com/tutorials/mobile-design-tutorials/mobile-design_png-or-jpg/
    http://mobile.tutsplus.com/tutorials/android/android-tablet-design/
    http://mobile.tutsplus.com/tutorials/appcelerator/build-a-titanium-mobile-pizza-ordering-app-order-form-setup/
    http://mobile.tutsplus.com/tutorials/corona/corona-sdk_brick-breaker/
    http://mobile.tutsplus.com/tutorials/android/android-sdk_tablet_virtual-device-configuration/
    http://mobile.tutsplus.com/tutorials/appcelerator/pizza-ordering-app-part-2/
    http://mobile.tutsplus.com/tutorials/iphone/1980s-phone-app_interface-builder-setup/

    ================================================================

    Thank you very much…

  • Mahmoud

    The application is crashed, didn’t know why?

    • http://eazyigz.wordpress.com Igor Ganapolsky

      What does your Logcat output say?

  • James

    How to add a header or footer of the list? Thanks!

  • http://www.thefleamarkets.com Martin

    where do you paste step #4 not very detailed on what to do with that piece of code.

    • Jim

      Your paste it inside the onCreate method. It is NOT a field variable…made that mistake myself.

  • Edd

    Hi thanks for the great tutorials. My tutlistactivity and tutvieweractivity are the same as the code above. Im sure my layouts and resources are correct and same with arrays and strings. Compiles fine then when i try to load the application unexpectedly closes. Logcat says the following:

    04-10 18:29:28.066: W/dalvikvm(1469): threadid=1: thread exiting with uncaught exception (group=0×40015560)
    04-10 18:29:28.319: E/AndroidRuntime(1469): FATAL EXCEPTION: main
    04-10 18:29:28.319: E/AndroidRuntime(1469): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.bcs.test/com.bcs.test.TutListActivity}: java.lang.NullPointerException
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1544)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1638)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.os.Handler.dispatchMessage(Handler.java:99)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.os.Looper.loop(Looper.java:123)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.app.ActivityThread.main(ActivityThread.java:3647)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at java.lang.reflect.Method.invokeNative(Native Method)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at java.lang.reflect.Method.invoke(Method.java:507)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at dalvik.system.NativeStart.main(Native Method)
    04-10 18:29:28.319: E/AndroidRuntime(1469): Caused by: java.lang.NullPointerException
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.content.ContextWrapper.getResources(ContextWrapper.java:80)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at com.bcs.test.TutListActivity.(TutListActivity.java:15)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at java.lang.Class.newInstanceImpl(Native Method)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at java.lang.Class.newInstance(Class.java:1409)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
    04-10 18:29:28.319: E/AndroidRuntime(1469): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1536)
    04-10 18:29:28.319: E/AndroidRuntime(1469): … 11 more
    04-10 18:29:28.576: W/ActivityManager(60): Force finishing activity com.bcs.test/.TutListActivity
    04-10 18:29:29.226: W/ActivityManager(60): Activity pause timeout for HistoryRecord{4053f4b8 com.bcs.test/.TutListActivity}
    04-10 18:29:35.036: D/dalvikvm(135): GC_EXPLICIT freed 178K, 50% free 3030K/5959K, external 4943K/6062K, paused 52ms
    04-10 18:29:39.436: D/dalvikvm(242): GC_EXPLICIT freed 8K, 55% free 2597K/5703K, external 1625K/2137K, paused 255ms
    04-10 18:29:42.436: D/SntpClient(60): request time failed: java.net.SocketException: Address family not supported by protocol
    04-10 18:29:44.109: W/ActivityManager(60): Activity destroy timeout for HistoryRecord{4053f4b8 com.bcs.test/.TutListActivity}
    04-10 18:29:45.292: D/dalvikvm(312): GC_EXPLICIT freed 3K, 54% free 2537K/5511K, external 1625K/2137K, paused 647ms

    Believe it may be problem with my androidmanifest.xml

    Any help would be greatly appreciated.

    Thanks

    • Gerry

      The String[] links array should be instantiated as a local variable, not a global

  • kala

    Hi there
    Very good tutorial.Please help me how to add Interner permission in manifest file.please reply.

  • kala

    **Internet permission

  • Shirad

    Place the below in your manifest file right before the tag:

    <uses-permission android:name=”android.permission.INTERNET”></uses-permission>

  • Ken

    I kept getting a compile error, so I downloaded the source from Google code, and get the same error.

    The problem is with this part:
    @Override
    public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {

    The error message in Eclipse says that the method must override a superclass method.

    I am using the latest version of Java, Eclipse, Android SDK, and Android tools plugin.

    Any suggestions?

    • Ken

      I found the problem, and I’ll share it here in case anyone else is struggling with this. The onItemClick method is defined as abstract, which means can be extended, not overridden. So when I took out the @Override it worked fine.

  • billy

    how to mainActivity (webview) > listViewActivity (select url) > pass url to mainActivity (webview), because i write this code Intent launchingIntent = getIntent(); in mainActivty , when program execute, it’s crash.

    any idea?

  • http://suputamadre.blogspot.com viktorvogh

    What about the AndroidManifest.xml file?

    I can’t start the ListActivity because it’s not correctly declared on the AndroidManifest.xml. I have it like this:

    could someone tell me how to declare it in the AndroidManifest.xml file?

  • Jakob Harteg

    Great tutorial, easy to follow while still being relatively quick! Thanks for this!!

  • Akhil Jain

    for all the people who are having inflate exception or binary xml error at line 2, try to set minimumsdk version to 11, there is error when trying to run this app on device/emulator below honeycomb

  • Dwinar

    It does not open any of those URLs after clicking on any of titles.