Creating a nice looking List dialog with images and text

This tutorial, will demonstrate how you can create a great looking selectiondialog, containing both text and images.

alt text

This list can then be used either directly in an Activity, Fragment, or as an Activity looking like a dialog. In this example, I will go with the latter, and create an activity that looks like a selection dialog window, that, in this case will be used to choose a country.

Creating such a selection list is easy if it should contain text only, but a bit more complicated if you also want to include images.

What we need:

Note: This entire example app is available for download on my Github page, see the last chapter.

  • A few images. here I will be using flag icons. Put the images in the res/drawables folder (create it if it does'n exist).
  • String array resources that contain the texts and image references
  • Two activities: MainActivity, that is the default activity, and CountrycodeActivity to display the list as a dialog.
  • One custom list adapter that we use to connect the resources to the ListView
  • Two simple layouts; one for the MainActivity and one that represents a list item, with the flag and country name.


First, create a new android app project. Then create the following files:

The MainActivity is the main screen we see after opening the app, this is just used to demonstrate the CountrycodeActivity selection dialog.

This activity registers a click listener on a button, which starts the CountrycodeActivity via an Intent.

The CountrycodeActivity is started with the startActivityForResult method, which expects a result back. The result is the selection which the user made, in onActivityResult.

public class MainActivity extends Activity {  
    private Button btn;
    protected void onCreate(Bundle savedInstanceState) {
        final Intent intent = new Intent(this, CountrycodeActivity.class);
        btn = (Button) findViewById(;
        btn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                startActivityForResult(intent, 1);
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 1 && resultCode == Activity.RESULT_OK){
            String countryCode = data.getStringExtra(CountrycodeActivity.RESULT_CONTRYCODE);
            Toast.makeText(this, "You selected countrycode: " + countryCode, Toast.LENGTH_LONG).show();


This is the layout for the MainActivity, containing just a button, to launch the country selection dalog.

<RelativeLayout xmlns:android=""  

        android:text="Show listdialog"
        android:layout_alignParentStart="true" />


The CountrycodeActivity class is a ListActivity that renders a list of countries, based on data from string.xml resources; names, values and images. We use the inner class called Country as a helper to hold the data from the resources.

The CountrycodeActivity uses a custom ListAdapter called CountryListArrayAdapter to render the custom list itself, we just pass it the data it should render.

The list is hooked up with a click listener, so we can detect when the user clicks an item.

Since this activity was started from the MainActivity, and is expected to return with a result, we will return the value of the selected country, when the user clicks on a list item, we do this by calling setResult() and then finish().

public class CountrycodeActivity extends ListActivity {

    public static String RESULT_CONTRYCODE = "countrycode";
    public String[] countrynames, countrycodes;
    private TypedArray imgs;
    private List<Country> countryList;

    protected void onCreate(Bundle savedInstanceState) {
        ArrayAdapter<Country> adapter = new CountryListArrayAdapter(this, countryList);
        getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Country c = countryList.get(position);
                Intent returnIntent = new Intent();
                returnIntent.putExtra(RESULT_CONTRYCODE, c.getCode());
                setResult(RESULT_OK, returnIntent);
                imgs.recycle(); //recycle images

    private void populateCountryList() {
        countryList = new ArrayList<Country>();
        countrynames = getResources().getStringArray(R.array.country_names);
        countrycodes = getResources().getStringArray(R.array.country_codes);
        imgs = getResources().obtainTypedArray(R.array.country_flags);
        for(int i = 0; i < countrycodes.length; i++){
            countryList.add(new Country(countrynames[i], countrycodes[i], imgs.getDrawable(i)));

    public class Country {
        private String name;
        private String code;
        private Drawable flag;
        public Country(String name, String code, Drawable flag){
   = name;
            this.code = code;
            this.flag = flag;
        public String getName() {
            return name;
        public Drawable getFlag() {
            return flag;
        public String getCode() {
            return code;

Ths is the custom ListAdapter that does just the rendering of the list based on the input country data.

The adapter renders each country as a row, with the custom layout defined in activity_countrycode_row.xml.

It makes use of the viewholder pattern to reuse existing views for performance, rather than always creating new ones.

public class CountryListArrayAdapter extends ArrayAdapter<CountrycodeActivity.Country> {

    private final List<CountrycodeActivity.Country> list;
    private final Activity context;

    static class ViewHolder {
        protected TextView name;
        protected ImageView flag;

    public CountryListArrayAdapter(Activity context, List<CountrycodeActivity.Country> list) {
        super(context, R.layout.activity_countrycode_row, list);
        this.context = context;
        this.list = list;

    public View getView(int position, View convertView, ViewGroup parent) {
        View view = null;

        if (convertView == null) {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.activity_countrycode_row, null);
            final ViewHolder viewHolder = new ViewHolder();
   = (TextView) view.findViewById(;
            viewHolder.flag = (ImageView) view.findViewById(;
        } else {
            view = convertView;

        ViewHolder holder = (ViewHolder) view.getTag();;
        return view;


This layout defines a row used in the CountryListArrayAdapter.

It contains an ImageView for the country flag, and a TextView to show the country name.

alt text

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android=""  
    android:padding="4dp" >

    <!-- Views with default image and text, for demonstration.
    They will be changed in the adapter -->
        android:layout_marginLeft="4dp" />

        android:layout_gravity="center_vertical" />



To be able to render the CountrycodeActivity as a dialog instead of a full screen activity, we must change the Activitys default theme. We can do this in the AndroidManifest.xml file.

Set the theme of the CountrycodeActivity to android:theme="@android:style/Theme.Holo.Light.Dialog".

Also, since this is used as a dialog, we don't want the dialog to show up in the list of recent apps, so add the excludeFromRecents="true" to the activity.

<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android=""  
    package="com.envyandroid.listdialogexample" >
        android:theme="@style/AppTheme" >
            android:label="@string/app_name" >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />

            android:label="Select your country">


This is where we define our string resources, and where we will put our country data.

We use string arrays to hold the country data.

  • The first string array holds the display names of the countries, what will be shown in the dialog.
  • The second array holds the values that will be returned to the MainActivity, so we know which country was selected. We could ofcourse drop this, and return the country display name instead, but then we would have to extract the countrycode or name from that string.
  • The last array contains references to the images that are shown for each country.

Note: The order of these arrays are important, as all three arrays correlate.

<?xml version="1.0" encoding="utf-8"?>  
    <string name="app_name">ListDialogExample</string>
    <!-- Order is important here: -->
    <string-array name="country_names">
        <item>\u00A0\u00A0+1 United States"</item>
        <item>+45 Denmark</item>
        <item>+46 Sweden</item>
        <item>+47 Norway</item>

    <string-array name="country_codes">

    <string-array name="country_flags">

There is a trick for the United States countrycode, as it is only one digit, it is padded with a preceeding hard space. I have written about this trick before.


alt text alt text alt text


This is just one way to make such a list dialog.

Instead of keeping the country data in the strings.xml file as string arrays, you could ofcourse put the data directly in the code or in a database and use a cursor, but I wanted to show how you could get this kind of data from the strings.xml file.

  • The code is small and simple to implement, and in my case, contains few items
  • It is easier to update the list of countries with new country elements, compared to using a database to hold the country list. (*)
  • The country_names can now easily be translated.

I also tried using dialogfragments, but couldn't quite get it working the way I wanted.

(*) on the other hand, if you were using a database, you could add new countries by downloading the strings and images from your server, but it would make it more difficult to manage and translate, and you would need permission to do network requests.

In this example, strings have been included inline in the code, for demonstration purpose, they should normally reside in the strings.xml file. You can easily extract and format string resources.

Samplecode on GitHub alt text

This complete working code sample is available on my GitHub page:


If you find any bugs, or want to contribute other solutions, you can submit a pull request :)

Please share this article!

comments powered by Disqus