ListView Sectioned Headers in Android
Sectioned headers in a list are great when you want to display categorized items eg. by time/day, by product category or sales price.
In this example, we will be using Jeff Sharkey’s Sectioned Headers to display journal entries by day.
File: main.xml
<?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>
File: list_header.xml
<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" />
File: list_item.xml
<?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" />
File: list_complex.xml
<?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>
File: add_journalentry_menuitem.xml
<?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" />
File: ListSample.java
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(); } }); } }
File: SeparatedListAdapter.java
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; } }
No comments:
Post a Comment