Custom Adapter for List View

public class ListAdapter extends ArrayAdapter<Item> {

    private int resourceLayout;
    private Context mContext;

    public ListAdapter(Context context, int resource, List<Item> items) {
        super(context, resource, items);
        this.resourceLayout = resource;
        this.mContext = context;
    }

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

        View v = convertView;

        if (v == null) {
            LayoutInflater vi;
            vi = LayoutInflater.from(mContext);
            v = vi.inflate(resourceLayout, null);
        }

        Item p = getItem(position);

        if (p != null) {
            TextView tt1 = (TextView) v.findViewById(R.id.id);
            TextView tt2 = (TextView) v.findViewById(R.id.categoryId);
            TextView tt3 = (TextView) v.findViewById(R.id.description);

            if (tt1 != null) {
                tt1.setText(p.getId());
            }

            if (tt2 != null) {
                tt2.setText(p.getCategory().getId());
            }

            if (tt3 != null) {
                tt3.setText(p.getDescription());
            }
        }

        return v;
    }

}

This is a class I had used for my project. You need to have a collection of your items which you want to display, in my case it's <Item>. You need to override View getView(int position, View convertView, ViewGroup parent) method.

R.layout.itemlistrow defines the row of the ListView.

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

    <TableRow android:layout_width="fill_parent"
              android:id="@+id/TableRow01"
              android:layout_height="wrap_content">

        <TextView android:textColor="#FFFFFF"
                  android:id="@+id/id"
                  android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  android:text="id" android:textStyle="bold" 
                  android:gravity="left"
                  android:layout_weight="1" 
                  android:typeface="monospace"
                  android:height="40sp" />
    </TableRow>

    <TableRow android:layout_height="wrap_content"
              android:layout_width="fill_parent">

        <TextView android:textColor="#FFFFFF" 
                  android:id="@+id/categoryId"
                  android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  android:text="categoryId" 
                  android:layout_weight="1" 
                  android:height="20sp" />

        <TextView android:layout_height="wrap_content"
                  android:layout_width="fill_parent" 
                  android:layout_weight="1"
                  android:textColor="#FFFFFF"
                  android:gravity="right"
                  android:id="@+id/description"
                  android:text="description" 
                  android:height="20sp" />
    </TableRow>

</TableLayout>

In the MainActivity define ListViewlike this,

ListView yourListView = (ListView) findViewById(R.id.itemListView);

// get data from the table by the ListAdapter
ListAdapter customAdapter = new ListAdapter(this, R.layout.itemlistrow, List<yourItem>);

yourListView .setAdapter(customAdapter);

I know this has already been answered... but I wanted to give a more complete example.

In my example, the ListActivity that will display our custom ListView is called OptionsActivity, because in my project this Activity is going to display the different options my user can set to control my app. There are two list item types, one list item type just has a TextView and the second list item type just has a Button. You can put any widgets you like inside each list item type, but I kept this example simple.

The getItemView() method checks to see which list items should be type 1 or type 2. According to my static ints I defined up top, the first 5 list items will be list item type 1, and the last 5 list items will be list item type 2. So if you compile and run this, you will have a ListView that has five items that just contain a Button, and then five items that just contain a TextView.

Below is the Activity code, the activity xml file, and an xml file for each list item type.

OptionsActivity.java:

public class OptionsActivity extends ListActivity {

    private static final int LIST_ITEM_TYPE_1 = 0;
    private static final int LIST_ITEM_TYPE_2 = 1;
    private static final int LIST_ITEM_TYPE_COUNT = 2;

    private static final int LIST_ITEM_COUNT = 10;
    // The first five list items will be list item type 1 
    // and the last five will be list item type 2
    private static final int LIST_ITEM_TYPE_1_COUNT = 5;

    private MyCustomAdapter mAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAdapter = new MyCustomAdapter();
        for (int i = 0; i < LIST_ITEM_COUNT; i++) {
          if (i < LIST_ITEM_TYPE_1_COUNT)
            mAdapter.addItem("item type 1");
          else
            mAdapter.addItem("item type 2");
        }
        setListAdapter(mAdapter);
    }

    private class MyCustomAdapter extends BaseAdapter {

        private ArrayList<String> mData = new ArrayList<String>();
        private LayoutInflater mInflater;

        public MyCustomAdapter() {
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        public void addItem(final String item) {
            mData.add(item);
            notifyDataSetChanged();
        }

        @Override
        public int getItemViewType(int position) {
          if(position < LIST_ITEM_TYPE_1_COUNT)
              return LIST_ITEM_TYPE_1;
          else
              return LIST_ITEM_TYPE_2;
        }

        @Override
        public int getViewTypeCount() {
            return LIST_ITEM_TYPE_COUNT;
        }

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

        @Override
        public String getItem(int position) {
            return mData.get(position);
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            int type = getItemViewType(position);
            if (convertView == null) {
                holder = new ViewHolder();
                switch(type) {
                    case LIST_ITEM_TYPE_1:
                        convertView = mInflater.inflate(R.layout.list_item_type1, null);
                        holder.textView = (TextView)convertView.findViewById(R.id.list_item_type1_text_view);
                        break;
                    case LIST_ITEM_TYPE_2:
                        convertView = mInflater.inflate(R.layout.list_item_type2, null);
                        holder.textView = (TextView)convertView.findViewById(R.id.list_item_type2_button);
                        break;
                }
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.textView.setText(mData.get(position));
            return convertView;
        }

    }

    public static class ViewHolder {
        public TextView textView;
    }

}

activity_options.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
     >

    <ListView
        android:id="@+id/optionsList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

list_item_type_1.xml:

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

    <TextView
        android:id="@+id/list_item_type1_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text goes here" />

</LinearLayout>

list_item_type2.xml:

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

    <Button
        android:id="@+id/list_item_type2_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button text goes here" />

</LinearLayout>