Where Technology meets magic

53 Posts
6 Posts
84 Posts
142 Posts
High Voltage
57 Posts
Image processing
5 Posts
4 Posts
3 Posts
27 Posts
11 Posts
7 Posts
3 Posts
21 Posts
19 Posts
9 Posts
9 Posts
91 Posts
2 Posts
23 Posts
Windows Mobile
11 Posts

Sponsored Links


Top Articles!

AVR SDCard FAT support with FatFS | 19620 Views | Rate 38.85
AVR SDCard FAT support with FatFS
Single Chip Computer | 1856 Views | Rate 29.46
Single Chip Computer
3V to 400V regulated inverter for Geiger counters | 2900 Views | Rate 18.71
3V to 400V regulated inverter for Geiger counters
Virtualmin Git return code 22 fatal: git-http-push failed | 111 Views | Rate 13.88
Virtualmin Git return code 22 fatal: git-http-push failed


News & Updates

2014-12-12, Virtualmin Git return code 22 fatal: git-http-push failed

2014-11-25, Electric Fence - 20KV pulses for perimeter defense

2014-10-29, Statie de monitorizare a radiatiei de fond in Timisoara

2014-10-29, uRADMonitor - Online Radiation monitoring station



Android Custom Complex Listview with Header (no XML)

By Radu Motisan Posted on February 1st, 2011 , 2081 Views (Rate 1.47)

In my last article on listviews, I presented how it is possible to create a custom listview with items containing more than a simple line of text, without the use of external XMLs. Now I come with a new challenge:

Yes, you can have this nice interface in your Android Project. Here is what you need to know:
1. We create a custom listview adapter as in the previous article. This will hold two String: first name and last name.
2. Based on position, we load the special graphics: the item with position 0, will be the top image. The last position item will be the bottom image. We have special images if the item before had content or if it was empty:

  2. //check current item in list
  3. boolean isEmpty = ( (item.getFirstName().length() == 0) &&
  4. (item.getLastName().length() == 0));
  7. boolean isPrevEmpty = false;
  8. if (prevItem == null)
  9. isPrevEmpty = true;
  10. else
  11. isPrevEmpty = ( (prevItem.getFirstName().length() == 0) &&
  12. (prevItem.getLastName().length() == 0));

To better understand how the background images for each item are combined, you have the source code included below, look for the RES folder to see the images.
3. Based on position, some of the items get special content, eg. the very first item is a Header, with an EditText and two ToggleButtons. Normally you would use these to sort the content of your list.
In CustomAdapter.java:

  2. //header
  3. if (position == 0) {

Will handle the EditText and the two toggle buttons. The toggle buttons are like check boxes, but they support images. The image is defined in an xml, filter_left.xml and filter_right.xml corresponding to the left and right togglebuttons. The XML is places together with the images, and the content is as follows:

  2. <?xml version="1.0" encoding="utf-8"?>
  3. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  4. <item android:state_checked="true"
  5. android:drawable="@drawable/filter_left_on" /> <!-- pressed -->
  6. <item android:drawable="@drawable/filter_left_off" /> <!-- default/unchecked -->
  7. </selector>

In CustomAdapter.java , the bottom item is handled as follows:

  2. else if (position == total - 1) {
  3. //-- this is the LAST LV ITEM --//

This position parameter , but also the total variable, are conveniently sent from within the CustomAdapter class:

  2. public View getView(int position, View convertView, ViewGroup parent)
  3. {
  4. CustomAdapterItem item = itemList.get(position);
  5. CustomAdapterItem prevItem = null;
  6. if (position > 0) prevItem = itemList.get(position-1);
  7. View v = new CustomAdapterView(this.context, item, position, itemList.size(), prevItem );
  8. return v;
  9. }

As you can see we access the previous item as well, to learn if it's populated or not, and use the proper image for out item in the listview:

If the previous item had content

If the previous item was empty

As you can see this helps to create a continuous interface listview.

To handle the click events and text change event in the top EditText, we set the callback back to the parent class:
In CustomAdapterView:

  2. setOnClickListener((OnClickListener) context);
  3. setId(item.getItemID());
  4. ...
  5. et.setId(CustomComplexListview.idFilterEdit);
  6. et.addTextChangedListener((TextWatcher) context);

But make sure the parent class, implements the click and text change events or your app will crash:

  2. public class CustomComplexListview extends Activity implements OnClickListener, TextWatcher {

The interface is vertically scrollable - a very nice effect, including the header moves together with the rest of the items.

When the application first starts, the listview is scrolled automatically so that the Header is hidden. A very nice effect for an elegant listview in your application. See: CustomComplexListview.java:

  2. m_lv.setSelection(1);

To populate the listview, I decided to process the top Header and the last bottom item separately. The reason is these are special items that do not get the normal content (first name + lastname):

  2. m_lv = new ListView(this);
  4. ArrayList<CustomAdapterItem> m_lvItems = new ArrayList<CustomAdapterItem>();
  5. //
  6. //add Header
  7. m_lvHeaderItem = new CustomAdapterItem("","",0); //add header
  8. m_lvItems.add(m_lvHeaderItem);
  9. //add items
  10. CustomAdapterItem lvItem;
  12. int items = 0;
  14. lvItem = new CustomAdapterItem( "Radu", "Motisan", idLVFirstItem+items);
  15. m_lvItems.add(lvItem);
  16. items++;
  18. lvItem = new CustomAdapterItem( "PocketMagic", ".net", idLVFirstItem+items);
  19. m_lvItems.add(lvItem);
  20. items++;
  22. lvItem = new CustomAdapterItem( "Complex", "Listview", idLVFirstItem+items);
  23. m_lvItems.add(lvItem);
  24. items++;
  26. // add extra items to fill the rest of the listview: we need 4 items at least!
  27. for (int i=0;i<4-items;i++) {
  28. lvItem = new CustomAdapterItem("","", 0);
  29. m_lvItems.add(lvItem);
  30. }
  32. //add Footer
  33. lvItem = new CustomAdapterItem("","",0); //add footer: must be last item!
  34. m_lvItems.add(lvItem);
  35. //create the Adapter
  36. if (m_lvAdapter == null) m_lvAdapter = new CustomAdapter(this, m_lvItems);
  37. //Add adapter to Listview
  38. m_lv.setAdapter((ListAdapter) m_lvAdapter);
  39. // Configure listview: no divider, no focusable, etc
  40. m_lv.setDividerHeight(0);
  41. m_lv.setScrollBarStyle(0);
  42. m_lv.setSelection(1);
  43. m_lv.setFocusable(false);

By default, besides the Header and the Footer (bottom big item), we always get 4 items (to fill the screen up). Also I use setDividerHeight(0) and setScrollBarStyle(0) to disable the separator line between listview items.

Inside one item, but also in the Header when we have the EditText and the two togglebuttons, we use Relative layouts to conveniently place the components, one relative to another:

  2. //the EditText
  3. et.setId(CustomComplexListview.idFilterEdit);
  4. et.setBackgroundResource(R.drawable.edit);
  5. et.addTextChangedListener((TextWatcher) context);
  6. RelativeLayout.LayoutParams layoutparams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  7. layoutparams.leftMargin = 0;
  8. layoutparams.topMargin = 0;
  9. PanelH.addView(et, layoutparams);
  10. ...
  11. //The First Toggle Button
  12. RelativeLayout.LayoutParams layoutparams1 = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  13. layoutparams1.addRule(RelativeLayout.BELOW, CustomComplexListview.idFilterEdit);
  14. layoutparams1.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
  15. PanelH.addView(b1, layoutparams1);

As you can see, we simply align the left toggle button below the EditText control. Extremely convenient!

You'll see all the details in my code:

If you have any questions, use the comments form below.

More on PocketMagic:

Atmega8 and enc28J60 for ethernet support | 8710 Views | Rate 9.98
Atmega8 and enc28J60 for ethernet support
How to set the AVR Fusebits | 6393 Views | Rate 9.85
How to set the AVR Fusebits
Custom Rotary Knob Control for Android | 3954 Views | Rate 9.64
Custom Rotary Knob Control for Android
Programmatically Injecting Events on Android - Part 1 | 8917 Views | Rate 9.24
Programmatically Injecting Events on Android - Part 1
Variable 0..30V Regulated Power supply for 20A max | 15171 Views | Rate 8.61
Variable 0..30V Regulated Power supply for 20A max
Discussing security in online on TV News show | 2650 Views | Rate 8.41
Discussing security in online on TV News show

6 Responses to “Android Custom Complex Listview with Header (no XML)”

  1. 1

    This app is getting failed when try to run

  2. 2
    Radu Motisan:

    @Sapna, you can compile the code yourself, source code available above.

  3. 3
    Андроид - создание Custom ListView | Мои IT-заметки:

    […] эту тему: http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/ http://www.pocketmagic.net/?p=1678 […]

  4. 4

    Hi ,

    Nice work ,But i need listview like in first some option is there if i choose any one it will navigate to second listview page.
    (ie “in first list view country,fruits option , if i choose country option navigate and show list of country “) this what i want

  5. 5
    Radu Motisan:

    you can use this article as a starting point for what you need

  6. 6
    Simple Gridview Control for Android « PocketMagic:

    […] to the previous article on a custom listview control, here we also need a custom adapter defined in GridViewAdapter.java, that provides the Gridview […]

Thank you for commenting. Your comment won't show until approved, which can take some time.