Android Multi Column ListView With Sticky Header Example

android recyclerview section header, android image slider from url, android multi column listview, android recyclerview multi column

Android Multi Column ListView With Sticky Header Example is today’s shining topic.

Multi column listview means that every row of the listview have more than one column and this listview is developing a table like structure.

You need to create a ListView with multiple columns in many applications to show multiple data.

Sometimes you want to have a static headers and just below that header, you want multi column listview.

For example, to show a order summary of any restaurant, you have two sticky headers like name of the restaurant and name of the customer.

Just after these two headers, your listview starts where every row includes columns like name of product, price of product, quantity of product etc.

We will develop just this kind of example in this article.

See Our MultiColumn ListView

Step 1. Making a List Item File

For creating a ListView, we need to make separate xml layout file.

This layout file represents the whole view structure of each listview row item.

So make a new file named list_item.xml in res->layout structure.

Add the below source code in list_item.xml file.

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#16a307"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:id="@+id/tvProduct"
            android:textColor="#fff"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_weight="2"
            android:text="Product Name"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:id="@+id/tvQty"
            android:textColor="#fff"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_weight="1"
            android:text="Quantity"/>

    </LinearLayout>

</LinearLayout>
  • In listview, we have two columns in every row item. One column is showing product name and another is showing the quantity of the product.
  • In the above list_item.xml file, two textviews are representing these two columns.
  • We will use this list_item.xml file in the adapter class where compiler will inflate it in every iteration while making each row for listview.

Step 2. Food Model

The proper way to make a reliable listview in every scenario is to make a listview with help of the model class.

Model class includes getter and setter methods for data maintenance.

For example, in our example we have data in the form of product name and it’s quantity.

We can store product name in String and quantity in integer format.

Create a new java class named FoodModel.java in your app.

Following is the coding lines for FoodModel.java class

public class FoodModel {

    private String product;
    private int qty;

    public String getProduct() {
        return product;
    }

    public void setProduct(String product) {
        this.product = product;
    }

    public int getQty() {
        return qty;
    }

    public void setQty(int qty) {
        this.qty = qty;
    }
}
  • As I have said earlier, above model class includes get and set method for both product name and quantity.

Step 3. Food Adapter Class

Now let us create a food adapter class which will generate data set for the listview.

Prepare a new java class and set it’s name as FoodAdapter.java

Write down the following lines in FoodAdapter.java class

public class FoodAdapter extends BaseAdapter {

    private Context context;
    private ArrayList<FoodModel> foodModelArrayList;

    public FoodAdapter(Context context, ArrayList<FoodModel> foodModelArrayList) {

        this.context = context;
        this.foodModelArrayList = foodModelArrayList;
    }

    @Override
    public int getViewTypeCount() {
        return getCount();
    }
    @Override
    public int getItemViewType(int position) {

        return position;
    }

    @Override
    public int getCount() {
        return foodModelArrayList.size();
    }

    @Override
    public Object getItem(int position) {
        return foodModelArrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            holder = new ViewHolder();
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.list_item, null, true);

            holder.tvProduct = (TextView) convertView.findViewById(R.id.tvProduct);
            holder.tvQty = (TextView) convertView.findViewById(R.id.tvQty);

            convertView.setTag(holder);
        }else {
            // the getTag returns the viewHolder object set as a tag to the view
            holder = (ViewHolder)convertView.getTag();
        }

        holder.tvProduct.setText(foodModelArrayList.get(position).getProduct());
        holder.tvQty.setText(String.valueOf(foodModelArrayList.get(position).getQty()));

        return convertView;
    }

    private class ViewHolder {

        protected TextView tvProduct, tvQty;

    }

}

Diving Step by Step

Hang on, we will now understand above code one by one snippets.

Consider the below code snippet

 private Context context;
 private ArrayList<FoodModel> foodModelArrayList;

    public FoodAdapter(Context context, ArrayList<FoodModel> foodModelArrayList) {

        this.context = context;
        this.foodModelArrayList = foodModelArrayList;
    }
  • First line is creating object of context.
  • Second is creating an ArrayList with the objects of the FoodModel class.
  • This arraylist (foodModelArrayList) is our main data provider. We are filling this arraylist (foodModelArrayList) with data in Main Activity. We will see this in next step.
  • Then I have created one Constructor. We will get context and arraylist (foodModelArrayList) via the parameters of this constructor.

Look at the below lines

@Override
    public int getViewTypeCount() {
        return getCount();
    }
    @Override
    public int getItemViewType(int position) {

        return position;
    }

    @Override
    public int getCount() {
        return foodModelArrayList.size();
    }

    @Override
    public Object getItem(int position) {
        return foodModelArrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }
  • Above are necessary method to be overriden. Mainly I have used that arraylist (foodModelArrayList)  in above methods.

Read the following code snippet

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            holder = new ViewHolder();
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.list_item, null, true);

            holder.tvProduct = (TextView) convertView.findViewById(R.id.tvProduct);
            holder.tvQty = (TextView) convertView.findViewById(R.id.tvQty);

            convertView.setTag(holder);
        }else {
            // the getTag returns the viewHolder object set as a tag to the view
            holder = (ViewHolder)convertView.getTag();
        }

        holder.tvProduct.setText(foodModelArrayList.get(position).getProduct());
        holder.tvQty.setText(String.valueOf(foodModelArrayList.get(position).getQty()));

        return convertView;
    }
  • Above getView() creates every row of the listview.
  • This method is called for the number of times which is equal to the number of rows of the listview.
  • For example, if listview have five rows then getView() method is called for five times.
  • In this getView() method, compiler will first inflate the row layout (list_item.xml) which we have already created in step 1.
  • Then we will fill the values of two textviews. (One is for product name and another is for quantity.)
  • We are using arraylist (foodModelArrayList) to fill the values in textviews.

Step 4. Making Final Changes

Now let us create our app’s main layout structure.

For this, you need to replace your existing code of activity_main.xml with the following one

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:gravity="center"
        android:background="#000"
        android:textSize="30sp"
        android:textColor="@color/colorAccent"
        android:text="Zyka Restaurant"
        />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:gravity="center"
        android:background="#000"
        android:textSize="25dp"
        android:textColor="@color/colorAccent"
        android:text="Oeder Summary"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#1ec2d4"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:textColor="#fff"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_weight="2"
            android:text="Product Name"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:textColor="#fff"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_weight="1"
            android:text="Quantity"/>

    </LinearLayout>

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="20dp"
        android:id="@+id/listView">

    </ListView>


</LinearLayout>
  • In the above file, I have added three sticky or static headers. It means that these headers can not be changed or modified.
  • First two TextViews and LinearLayout with horizontal orientation represents these three sticky headers.
  • Just below these headers, I have added our multi column listview.

After this, write down the below code snippet in MainActivity.java file.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private String[] Products = new String[]{"Pizza", "Burger", "Pasta", "Salad", "Rice","Sandwich","Chips"};
    private int[] Qty = new int[]{3, 4, 2, 1, 5,8,20};
    private ArrayList<FoodModel> foodModelArrayList;
    private ListView listView;

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

        listView = findViewById(R.id.listView);

        //foodModelArrayList = new ArrayList<>();
        foodModelArrayList = populateList();

        FoodAdapter foodAdapter = new FoodAdapter(this,foodModelArrayList);
        listView.setAdapter(foodAdapter);

    }

    private ArrayList<FoodModel> populateList(){

        ArrayList<FoodModel> list = new ArrayList<>();

        for(int i = 0; i < 7; i++){
            FoodModel foodModel = new FoodModel();
            foodModel.setProduct(Products[i]);
            foodModel.setQty(Qty[i]);
            list.add(foodModel);
        }

        return list;
    }
}

What does above code means ?

See the below snippet

    private String[] Products = new String[]{"Pizza", "Burger", "Pasta", "Salad", "Rice","Sandwich","Chips"};
    private int[] Qty = new int[]{3, 4, 2, 1, 5,8,20};
    private ArrayList<FoodModel> foodModelArrayList;
    private ListView listView;
  • First line is creating one string array called Products. It includes the names of the various food products.
  • Similarly, second line is creating one integer array which holds the quantity of the food products.
  • Third and fourth lines are making objects ArrayList and Listview respectively.

Attend below lines

 foodModelArrayList = populateList();

 FoodAdapter foodAdapter = new FoodAdapter(this,foodModelArrayList);
 listView.setAdapter(foodAdapter);
  • Second line is creating a new object of FoodAdapter class and third one is setting this adapter object with the ListView.
  • First line will insert the data in foodModelArrayList using populateList() method.

populateList() method holds the below code

 private ArrayList<FoodModel> populateList(){

        ArrayList<FoodModel> list = new ArrayList<>();

        for(int i = 0; i < 7; i++){
            FoodModel foodModel = new FoodModel();
            foodModel.setProduct(Products[i]);
            foodModel.setQty(Qty[i]);
            list.add(foodModel);
        }

        return list;
    }
  • One for loop is there with six iterations.
  • In every iteration, compiler will create the object of the FoodModel class.

Then it will set the product name and quantity to this object. After this, compiler adds this object in the arraylist.

Download Source Code for Android Multi Column ListView

[sociallocker]Download Source Code For ListView_Multi_Column[/sociallocker]