ListView with Odd/Even rows in Android

    Sometimes, we can see ListView with  alternate styles: for odd position having a different layout and for even position of  list item having another layout as well as different appearance.
    In this post, I will present how to make a ListView like this:


First, declaring some layouts in xml files:
- Activity layout:
activity_main.xml
<RelativeLayout 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="@android:color/white" >

    <LinearLayout
        android:id="@+id/layout_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_blue_dark"
        android:padding="10dp" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/friend"
            android:textColor="@android:color/white" />
    </LinearLayout>

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/layout_header" />

</RelativeLayout>
- Odd row layout:
item_odd_listview.xml
<LinearLayout 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="#F5EEE5"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/gender_image"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="39.5"
        android:contentDescription="@string/app_name"
        android:src="@drawable/ic_launcher" />

    <View
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="0.5"
        android:background="@android:color/holo_green_dark" />

    <TextView
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_weight="60"
        android:gravity="center"
        android:textColor="@android:color/holo_green_dark" />

</LinearLayout>
- Even row layout:
item_even_listview.xml
<LinearLayout 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="#F5EEE5"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_weight="60"
        android:gravity="center"
        android:textColor="@android:color/holo_blue_dark" />

    <View
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="0.5"
        android:background="@android:color/holo_blue_bright" />

    <ImageView
        android:id="@+id/gender_image"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="39.5"
        android:contentDescription="@string/app_name"
        android:src="@drawable/ic_launcher" />

</LinearLayout>
To do this requirement, we must customize a ListView adapter based on ArrayAdapter, and in getView() method, providing 2 row styles depend on row's position. For more details, I commented in adapter source code:
ListViewAdapter.java
package com.blogspot.hongthaiit.listview;

import java.util.List;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ListViewAdapter extends ArrayAdapter<FriendInfor> {

 private Activity activity;

 public ListViewAdapter(Activity activity, int resource, List<FriendInfor> objects) {
  super(activity, resource, objects);
  this.activity = activity;
 }

 @Override
 public int getViewTypeCount() {
  // return the total number of view types. this value should never change
  // at runtime
  return 2;
 }

 @Override
 public int getItemViewType(int position) {
  // return a value between 0 and (getViewTypeCount - 1)
  return position % 2;
 }

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

  // inflate layout from xml
  LayoutInflater inflater = (LayoutInflater) activity
    .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

  int layoutResource = 0; // determined by view type
  int viewType = getItemViewType(position);
  switch (viewType) {
  case 0:
   layoutResource = R.layout.item_even_listview;
   break;

  case 1:
   layoutResource = R.layout.item_odd_listview;
   break;
  }

  if (convertView != null) {
   holder = (ViewHolder) convertView.getTag();
  } else {
   convertView = inflater.inflate(layoutResource, parent, false);
   holder = new ViewHolder(convertView);
   convertView.setTag(holder);
  }

  // set data to views
  if (getItem(position).isGender()) {
   holder.gender.setImageResource(R.drawable.male);
  } else {
   holder.gender.setImageResource(R.drawable.female);
  }
  holder.name.setText(getItem(position).getName());

  return convertView;
 }

 private class ViewHolder {
  private ImageView gender;
  private TextView name;

  public ViewHolder(View v) {
   gender = (ImageView) v.findViewById(R.id.gender_image);
   name = (TextView) v.findViewById(R.id.name);
  }
 }

}
Now, in our Activity programmatically code, we locate views and set adapter/adapter data to our own ListView:
MainActivity.java
package com.blogspot.hongthaiit.listview;

import java.util.LinkedList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends Activity {

 private ListView listView;
 private LinkedList<FriendInfor> friends;
 private ListViewAdapter adapter;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  listView = (ListView)findViewById(R.id.list);
  setData();
  setListViewAdapter();
 }

 private void setListViewAdapter() {
  adapter = new ListViewAdapter(this, R.layout.item_even_listview, friends);
  listView.setAdapter(adapter);
 }

 //set "demo" data for list view adapter
 private void setData() {
  friends = new LinkedList<FriendInfor>();
  
  friends.add(new FriendInfor("Hoàng Biên", false));
  friends.add(new FriendInfor("Đăng Chuyên", true));
  friends.add(new FriendInfor("Đinh Tuấn", true));
  friends.add(new FriendInfor("Quỳnh Trang", false));
  friends.add(new FriendInfor("Hồng Thái", true));
  friends.add(new FriendInfor("Bùi Hậu", false));
  friends.add(new FriendInfor("Hoàng Thành", true));
  friends.add(new FriendInfor("Quốc Cường", true));
  friends.add(new FriendInfor("Linh Phương", false));
  friends.add(new FriendInfor("Thùy Linh", false));
  friends.add(new FriendInfor("Đức Tú", true));
 }
}
Finally, adding this necessary file (model object in data):
FriendInfor.java
package com.blogspot.hongthaiit.listview;

public class FriendInfor {

 private String name;
 private boolean gender;
 
 public FriendInfor(String name, boolean gender) {
  this.name = name;
  this.gender = gender;
 }
 
 public String getName() {
  return name;
 }
 public boolean isGender() {
  return gender;
 }
 
}
Running program, we have this output:


Share


Previous post
« Prev Post
Next post
Next Post »