shaobin0604
11/20/2013 - 6:55 AM

Android – Sectioned Headers in ListViews

Android – Sectioned Headers in ListViews

import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
 
public class ListSample extends Activity
    {
 
        public final static String ITEM_TITLE = "title";
        public final static String ITEM_CAPTION = "caption";
 
        // SectionHeaders
        private final static String[] days = new String[]{"Mon", "Tue", "Wed", "Thur", "Fri"};
 
        // Section Contents
        private final static String[] notes = new String[]{"Ate Breakfast", "Ran a Marathan ...yah really", "Slept all day"};
 
        // MENU - ListView
        private ListView addJournalEntryItem;
 
        // Adapter for ListView Contents
        private SeparatedListAdapter adapter;
 
        // ListView Contents
        private ListView journalListView;
 
        public Map<String, ?> createItem(String title, String caption)
            {
                Map<String, String> item = new HashMap<String, String>();
                item.put(ITEM_TITLE, title);
                item.put(ITEM_CAPTION, caption);
                return item;
            }
 
        @Override
        public void onCreate(Bundle icicle)
            {
                super.onCreate(icicle);
 
                // Sets the View Layer
                setContentView(R.layout.main);
 
                // Interactive Tools
                final ArrayAdapter<String> journalEntryAdapter = new ArrayAdapter<String>(this, R.layout.add_journalentry_menuitem, new String[]{"Add Journal Entry"});
 
                // AddJournalEntryItem
                addJournalEntryItem = (ListView) this.findViewById(R.id.add_journalentry_menuitem);
                addJournalEntryItem.setAdapter(journalEntryAdapter);
                addJournalEntryItem.setOnItemClickListener(new OnItemClickListener()
                    {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long duration)
                            {
                                String item = journalEntryAdapter.getItem(position);
                                Toast.makeText(getApplicationContext(), item, Toast.LENGTH_SHORT).show();
                            }
                    });
 
                // Create the ListView Adapter
                adapter = new SeparatedListAdapter(this);
                ArrayAdapter<String> listadapter = new ArrayAdapter<String>(this, R.layout.list_item, notes);
 
                // Add Sections
                for (int i = 0; i < days.length; i++)
                    {
                        adapter.addSection(days[i], listadapter);
                    }
 
                // Get a reference to the ListView holder
                journalListView = (ListView) this.findViewById(R.id.list_journal);
 
                // Set the adapter on the ListView holder
                journalListView.setAdapter(adapter);
 
                // Listen for Click events
                journalListView.setOnItemClickListener(new OnItemClickListener()
                    {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long duration)
                            {
                                String item = (String) adapter.getItem(position);
                                Toast.makeText(getApplicationContext(), item, Toast.LENGTH_SHORT).show();
                            }
                    });
            }
 
    }
import java.util.LinkedHashMap;
import java.util.Map;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
 
public class SeparatedListAdapter extends BaseAdapter
    {
        public final Map<String, Adapter> sections = new LinkedHashMap<String, Adapter>();
        public final ArrayAdapter<String> headers;
        public final static int TYPE_SECTION_HEADER = 0;
 
        public SeparatedListAdapter(Context context)
            {
                headers = new ArrayAdapter<String>(context, R.layout.list_header);
            }
 
        public void addSection(String section, Adapter adapter)
            {
                this.headers.add(section);
                this.sections.put(section, adapter);
            }
 
        public Object getItem(int position)
            {
                for (Object section : this.sections.keySet())
                    {
                        Adapter adapter = sections.get(section);
                        int size = adapter.getCount() + 1;
 
                        // check if position inside this section
                        if (position == 0) return section;
                        if (position < size) return adapter.getItem(position - 1);
 
                        // otherwise jump into next section
                        position -= size;
                    }
                return null;
            }
 
        public int getCount()
            {
                // total together all sections, plus one for each section header
                int total = 0;
                for (Adapter adapter : this.sections.values())
                    total += adapter.getCount() + 1;
                return total;
            }
 
        @Override
        public int getViewTypeCount()
            {
                // assume that headers count as one, then total all sections
                int total = 1;
                for (Adapter adapter : this.sections.values())
                    total += adapter.getViewTypeCount();
                return total;
            }
 
        @Override
        public int getItemViewType(int position)
            {
                int type = 1;
                for (Object section : this.sections.keySet())
                    {
                        Adapter adapter = sections.get(section);
                        int size = adapter.getCount() + 1;
 
                        // check if position inside this section
                        if (position == 0) return TYPE_SECTION_HEADER;
                        if (position < size) return type + adapter.getItemViewType(position - 1);
 
                        // otherwise jump into next section
                        position -= size;
                        type += adapter.getViewTypeCount();
                    }
                return -1;
            }
 
        public boolean areAllItemsSelectable()
            {
                return false;
            }
 
        @Override
        public boolean isEnabled(int position)
            {
                return (getItemViewType(position) != TYPE_SECTION_HEADER);
            }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent)
            {
                int sectionnum = 0;
                for (Object section : this.sections.keySet())
                    {
                        Adapter adapter = sections.get(section);
                        int size = adapter.getCount() + 1;
 
                        // check if position inside this section
                        if (position == 0) return headers.getView(sectionnum, convertView, parent);
                        if (position < size) return adapter.getView(position - 1, convertView, parent);
 
                        // otherwise jump into next section
                        position -= size;
                        sectionnum++;
                    }
                return null;
            }
 
        @Override
        public long getItemId(int position)
            {
                return position;
            }
 
    }
<?xml version="1.0" encoding="utf-8"?>
<!-- list_item.xml -->
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_item_title"
    android:gravity="right"
    android:drawableRight="@drawable/ic_menu_add"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:paddingTop="0dip"
    android:paddingBottom="0dip"
    android:paddingLeft="10dip"
    android:textAppearance="?android:attr/textAppearanceLarge" />
<?xml version="1.0" encoding="utf-8"?>
<!-- list_complex.xml -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingTop="10dip"
    android:paddingBottom="10dip"
    android:paddingLeft="15dip">
    <TextView
        android:id="@+id/list_complex_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"/>
    <TextView
        android:id="@+id/list_complex_caption"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_header_title"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:paddingTop="2dip"
    android:paddingBottom="2dip"
    android:paddingLeft="5dip"
    style="?android:attr/listSeparatorTextViewStyle" />
<?xml version="1.0" encoding="utf-8"?>
<!-- list_item.xml -->
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_item_title"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:paddingTop="10dip"
    android:paddingBottom="10dip"
    android:paddingLeft="15dip"
    android:textAppearance="?android:attr/textAppearanceLarge" />
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
 
    <ListView
        android:id="@+id/add_journalentry_menuitem"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <ListView
        android:id="@+id/list_journal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</LinearLayout>