Android Customized ListView

In the last tutorial of Android tutorial series, we developed a simple ListView application. This tutorial enhance the same application by customizing the ListView. After completing this tutorial, you must be able to create a custom Adapter and display customized ListView using that adapter. If you are not familiar with Android ListView, please follow this article and develop a Simple ListView application first, because this tutorial is a continuation of previous tutorial.

Step 1:
Create a new Android project with a package name com.javahelps.sample.customizedlistview and follow the steps given in the Android ListView article to create a basic ListView application. If you are already familiar with ListView, just download the template from this link and continue.

Step 2:
Run your application and test the application. It should list all 23 design patterns and if you click on any design pattern a short description should be displayed.

Step 3:
All these 23 design patterns are divided into three major types which are:
  • Behavioral design patterns
  • Creational design patterns
  • Structural design patterns
Our application should display icons in front of the name of design patterns based on these types. The images I have used are provided at this link. If you are interested download and use them, otherwise find some other suitable PNG images.

Step 4:
(Install the Android Drawable Importer plugin, if you do not have it.) Right click on the drawable folder and select NewScaled Drawable option (This option is provided by Android Drawable Importer plugin).


In the opened dialog add the img_behavioural, img_creational and img_strctural images using the "+" button.


Unselect the XXHDPI and XXXHDPI options, and click the OK button. Now in your dawable folder the imported images must be listed as shown below.


Step 5:
Copy the img_background.jpg image and paste it inside the drawable folder (Right click on drawable and select Paste). In the “Choose Destination Directory” dialog select the “../app.src/main/res/drawable” and click OK.


 In the next Copy dialog make sure the New name is img_background.jpg and click OK.


Now we have imported all the necessary images into the project.

Step 6:
Open the activity_main.xml and add an android:background="@drawable/img_background" attribute to the FrameLayout as shown below.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/img_background"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

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

Step 7:
Right click on layout folder and select NewXMLLayout XML File


Step 8:
In the New Android Activity dialog change the "Layout File Name" as list_item_layout and click on the Finish button.


Step 9:
Open the list_item_layout.xml in XML editor and replace the content of XML file by the following code and save all the changes.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="20dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="20dp">

    <ImageView
        android:id="@+id/imgIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/img_behavioural" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginStart="10dp">

        <TextView
            android:id="@+id/txtItem"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:text="Item"
            android:textAppearance="?android:attr/textAppearanceLarge" />
    </RelativeLayout>

</LinearLayout>

Step 10:
Open the MainActivity.java and create an inner class CustomAdapter as shown here.
private class CustomAdapter extends ArrayAdapter<String> {

    public CustomAdapter(Context context, String[] objects) {
        super(context, 0, objects);
    }

}
As discussed in Android ListView tutorial ArrayAdapter is used to feed an array or java.util.List to any ListView. In this code we create our own ArrayAdapter by extending the ArrayAdapter class. Since the type of array is String we use the generic <String> for ArrayAdapter.

Step 11:
Arrayadapter has a getView method which is used to provide a layout for the ListView items. We need to override the getView method and return a customized layout whenever the getView method is called. Override the getView method as shown here.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Create convertView only for the first time
    if (convertView == null) {
        convertView = getLayoutInflater().inflate(R.layout.list_item_layout, parent, false);
    }
    // Find the ImageView from convertView
    ImageView imgIcon = (ImageView) convertView.findViewById(R.id.imgIcon);
    // Find the TextView from convertView
    TextView txtItem = (TextView) convertView.findViewById(R.id.txtItem);
    // According to the position of item determine the icon
    int drawable;
    if (position >= 0 && position <= 4) {
        // Creational design pattern
        drawable = R.drawable.img_creational;
    } else if (position >= 5 && position <= 11) {
        // Structural design pattern
        drawable = R.drawable.img_structural;
    } else {
        // Behavioral design pattern
        drawable = R.drawable.img_behavioural;
    }
    // Set the icon to ImageView
    imgIcon.setImageResource(drawable);
    // Set the design pattern name to TextView
    txtItem.setText(designPatterns[position]);

    return convertView;
}
Let's analyze the code. The convertView is used as a single item in a ListView (Every item listed in a ListView is a clone of this convertView object). When ListView builds its interface, it calls the getView method of the provided Adapter with the position for which it needs the new View (position), recently used View(convertView), and a parent of the View (parent). For the first item (position = 0) convertView is null. If it is null, we create a View using LayoutInflater. LayoutInflater is used to instantiate a layout XML file into its corresponding View object.
Then we call the findViewById method which is used to identify the ImageView and TextView which we have defined in our list_item_layout.xml.
In the designPatterns array, the first 5 design patterns are creational design patterns. The next 7 design patterns are the structural design patterns. The last 11 design patterns are behavioral design patterns. According to their position, icon is determined in this code. Finally, we assign the design pattern name to TextView and the image to ImageView and return the convertView object.

Step 12:
Now instead of default ArrayAdapter, create a CustomAdapter and set it to the ListView as shown here.
ArrayAdapter<String> adapter = new CustomAdapter(this, designPatterns);
listView.setAdapter(adapter);
The final MainActivity.java is given below.
package com.javahelps.sample.customizedlistview;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;


public class MainActivity extends ActionBarActivity {
    private ListView listView;
    private String[] designPatterns;
    private String[] descriptions;

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

    // Find the list view
    this.listView = (ListView) findViewById(R.id.listView);

    // Create the arrays
    this.designPatterns = getResources().getStringArray(R.array.design_patterns);
    this.descriptions = getResources().getStringArray(R.array.design_patterns_description);

    // Create an array adapter
    ArrayAdapter<String> adapter = new CustomAdapter(this, designPatterns);
    listView.setAdapter(adapter);

    // Set item click listener
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        onListItemClicked(position);
        }
    });
    }

    private void onListItemClicked(int index) {
    String description = descriptions[index];
    Toast.makeText(this, description, Toast.LENGTH_SHORT).show();
    }

    private class CustomAdapter extends ArrayAdapter<String> {

    public CustomAdapter(Context context, String[] objects) {
        super(context, 0, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Create convertView only for the first time
        if (convertView == null) {
        convertView = getLayoutInflater().inflate(R.layout.list_item_layout, parent, false);
        }
        // Find the ImageView from convertView
        ImageView imgIcon = (ImageView) convertView.findViewById(R.id.imgIcon);
        // Find the TextView from convertView
        TextView txtItem = (TextView) convertView.findViewById(R.id.txtItem);
        // According to the position of item determine the icon
        int drawable;
        if (position >= 0 && position <= 4) {
        // Creational design pattern
        drawable = R.drawable.img_creational;
        } else if (position >= 5 && position <= 11) {
        // Structural design pattern
        drawable = R.drawable.img_structural;
        } else {
        // Behavioral design pattern
        drawable = R.drawable.img_behavioural;
        }
        // Set the icon to ImageView
        imgIcon.setImageResource(drawable);
        // Set the design pattern name to TextView
        txtItem.setText(designPatterns[position]);

        return convertView;
    }
    }
}

Step 13:
Save all the changes and run the application.

For the completed project, click on this link.

Sample Problem
A template for the application is provided at this link. This application downloads some quotes from Internet and display them in a ListView. Currently it just displays the quotes only. You are required to customize the ListView to display the author name at the left bottom of every quote as show below. (Use getPreview() and getAuthor() methods of Quote objects to get the preview and the author's name.)


Note: This project needs Internet access, so when you run this application make sure that you have an active Internet connection.

Find the projects at Git Hub.
Previous
Next Post »

2 comments

Write comments
saba ch
AUTHOR
September 9, 2016 at 7:01 PM delete

Sir i want the output as hotels names and also rates on the right of these names and these both fields access by external sqlite.the output should be displayed in listview.as above sample proble but the data should be accessed fro assets folder.tell me the solution.plssss

Reply
avatar
Gobinath
AUTHOR
September 10, 2016 at 8:47 AM delete

Hi,
Deploying the database from an external db as explained in [1] or [2] does not affect the way you represent them. Retrieve the hotel information as a List of objects and then feed them to the custom adapter. The abstract of the solution is given below:
1. First of all create a class Hotel with name and rating.
2. When you read the data from database in DatabaseAccess class (See Step 9 in [1]), read both name and rating columns, construct the Hotel objects and return them as a List
3. Feed the List to your custom adapter
4. From custom adapter, set the values to appropriate TextViews

[1] http://www.javahelps.com/2015/04/import-and-use-external-database-in.html
[2] http://www.javahelps.com/2016/07/deploy-and-upgrade-android-database.html

Reply
avatar

Contact Form

Name

Email *

Message *