Getting to know ListView in Android
Tags: android, listview, kotlin
Published: 2018-01-12 03:34:03

---
title: Getting to know ListView in Android
published: true
tags: #android #listview #kotlin 
cover_image: https://thepracticaldev.s3.amazonaws.com/i/brnu0efspmrpk93rbb27.png
---

### WARNING

**This will be a loooong post, so take your time to read through it.**

_The following code samples are written in [Kotlin](https://kotlinlang.org/) and I will asume that you are a bit familiar with Android Studio and the project structure of a basic Android app._

If you are currently learning Android development, chances are that you will come across with `ListView`. Which is a special kind of `View` used for displaying a `list of items` (I can already hear you thinking: "duh!") that is quite common in Android.

Although, it is being replaced by `RecycleView` because of performance and animations limitations that the `ListView` faces.

But it's good for you to be at least familiar with how it works, as it might also help you understand why and how `RecycleView` works later on.

# Requirements

- [Java SDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
- [Android Studio](https://developer.android.com/studio/index.html) (I'll be using version 3.0.1).
- Kotlin (Android Studio 3.0 or later comes with it built-in).
- [Kotlin Android Extensions](https://kotlinlang.org/docs/tutorials/android-plugin.html) (so we don't have to use `findViewById()` anymore)

# Setup the layout

Head over to your `activity_main.xml`, which should initially look like this:

```xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.chrisvasqm.gettingtoknowlistview.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
```

The default layout consists of a `TextView` on the center of the screen via constraints. Cool, but we won't need that, so go ahead and 🗑️ it.

We will replace everything with:

```xml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
```

Now if you check your Android Studio's Preview panel, it should look like this:

![Preview panel](https://thepracticaldev.s3.amazonaws.com/i/ffqni9k2afgtyk9ixotd.png)

Great! We can see that the list is already showing some content.

So, let's go ahead and try it out. Run the app on your device/emulator.

Got a blank screen? Awesome! That's what is expected 👍.

### Why?

Because the `ListView` shows those sample items so you can see how it would look when you fill it with data, but we haven't done that... yet.

# Adding data to the `ListView`

There are various ways to achieve this, I'll show you all 3 of them (unless there's more and I'm not aware of them).

## 1) Using a string-array resource file

The simplest way to fill a `ListView` is by using a `string-array` resource file.

Head over to your `app/res/values/` folder and create a new XML file, let's call it `arrays.xml`, then add the following code to it:

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="list_items">
        <item>One</item>
        <item>Two</item>
        <item>Three</item>
        <item>Four</item>
        <item>Five</item>
    </string-array>
</resources>
```

In order to add it our `ListView`, we can do it right inside the `activity_main.xml` layout by adding the the `entries` attribute to it:

```xml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:entries="@array/list_items"/>
```

Now run the app again and you should be able to see this:

![List of items](https://thepracticaldev.s3.amazonaws.com/i/qytdut5zqk0air8ku3wi.png)

## 2) Using an ArrayList & ArrayAdapter

In order to do this, we'll need to add an `id` attribute to our `ListView`, I'll name it "listView":

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

Then, head over to your `MainActivity.java` and make a `List<>` of `String`s:

```java
val items = listOf(
    "First",
    "Second",
    "Third",
    "Fourth",
    "Fifth"
)
```

The `listOf()` function takes in any number of arguments and returns a `List<TYPE>` object of that same type.

Plus, **it is immutable**. And by that I mean that it does not have any `add()` or `remove()` methods, like a regular `List` would have. In order to get them, you must use the `mutableListOf()` method instead.

Now we need to pass in our `items` list to an ArrayAdapter object:

```java
val arrayAdapter = ArrayAdapter<String>(
    this,
    android.R.layout.simple_list_item_1,
    items
)
```

The `android.R.layout.simple_list_item_1` is a layout made out of only a `TextView` that is part of the `android` package that has a R.layout folder, which holds commonly used resources so we don't have to make our own (but we will in our next section).

Now that we have our `arrayAdapter` ready, we can set our `ListViews`'s adapter to it:

```java
listView.adapter = arrayAdapter
```

Our MainActivity's `OnCreate` method should look like this now:

```java
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val items = listOf(
        "First",
        "Second",
        "Third",
        "Fourth",
        "Fifth"
    )

    val arrayAdapter = ArrayAdapter<String>(
        this,
        android.R.layout.simple_list_item_1,
        items
    )

    listView.adapter = arrayAdapter
}
```

What are you waiting for? go run the app and check it out yourself!

You should be able to see this now:

![ListView working with ArrayAdapter](https://thepracticaldev.s3.amazonaws.com/i/lqa9q0o6iq3n330fhnpj.png)

Well done, but... let's take it to the next level 😎!

## 3) Using a Custom ArrayAdapter

At the end of this section, we will be doing this:

![ListView with CustomArrayAdapter](https://thepracticaldev.s3.amazonaws.com/i/s71jl8313180sg53wzvr.png)

First thing we will need is to create a `class` that will hold our Contact related data:

```java
class Contact(
    val imageResource: Int,
    val name: String,
    val description: String
)
```

Now we can create our Custom ArrayAdapter by creating a `class` that will inherit from the ArrayAdapter `class` and since we are going to be displaying `Contact`s, I will name it `ContactArrayAdapter`:

```java
class ContactArrayAdapter(context: Context, contacts: List<Contact>)
    : ArrayAdapter<Contact>(context, 0, contacts) {

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val rootView = convertView ?: LayoutInflater.from(context).inflate(R.layout.list_item, parent, false)
        val currentContact = getItem(position)

        rootView.contactImage.setImageResource(currentContact.imageResource)
        rootView.contactName.text = currentContact.name
        rootView.contactDescription.text = currentContact.description

        return rootView
    }
}
```

You will probably notice that the `R.layout.list_item` will be highlighted with red, that's because we haven't created our custom layout that will show our `contactImage`, `contactName` and `contactDescription`.

Head over to your `app/res/layout/` folder, `Right Click` on the `layout` folder and select `New > Layout resource file`. Name it "list_item" and hit OK.

Now add this XML to it:

```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="16dp">

    <ImageView
        android:id="@+id/contactImage"
        android:layout_width="64dp"
        android:layout_height="64dp"
        app:srcCompat="@mipmap/ic_launcher_round" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:paddingLeft="16dp">

        <TextView
            android:id="@+id/contactName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Contact Name"
            android:textColor="@android:color/black"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/contactDescription"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Contact Description" />
    </LinearLayout>

</LinearLayout>
```

Copy our profile images from [my profile](https://dev.to/chrisvasqm) and [Jorge's](https://dev.to/dpbacross), and then paste them in your `app/res/drawable/` folder.

And now we finally have everything in place to set things in motion.

Go back to your `MainActivity` and refactor it so we now have a `List<Contact>` and instead of using the `ArrayAdapter<String>` we will use our new `ContactArrayAdapter`.

Which should look like:

```java
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val contacts = listOf(
                Contact(R.drawable.contact_chris, "Christian Vasquez", "QA Analyst"),
                Contact(R.drawable.contact_david, "Jorge Peña", ".NET Web Developer")
        )

        val arrayAdapter = ContactArrayAdapter(this, contacts)

        listView.adapter = arrayAdapter
    }
}
```

Run the app and you should be able to see our final result:

![ListView with CustomArrayAdapter](https://thepracticaldev.s3.amazonaws.com/i/s71jl8313180sg53wzvr.png)

What? Your images aren't circular?

Oh... I'll leave that as a homework for you :)

Cough cough [hint](https://github.com/hdodenhof/CircleImageView) cough cough.

# Final words

YOU MADE IT 👏👏👏

Make sure you high five yourself because THAT was a lot of work!

And I hope you learned something new along the way 🤓.