PocketMagic

PocketMagic

Where Technology meets magic


Android
53 Posts
BlackBerry
6 Posts
Electronics
84 Posts
Hardware
142 Posts
High Voltage
57 Posts
Image processing
5 Posts
iPhone
4 Posts
Linux
2 Posts
Nuclear
27 Posts
Optics
11 Posts
Photography
7 Posts
Photoshop
3 Posts
Research
21 Posts
Reviews
19 Posts
Robotics
9 Posts
Security
9 Posts
Software
90 Posts
Symbian
2 Posts
Tubes
23 Posts
Windows Mobile
11 Posts

Sponsored Links


   

Top Articles!


AVR SDCard FAT support with FatFS | 17503 Views | Rate 36.39
AVR SDCard FAT support with FatFS
Single Chip Computer | 1259 Views | Rate 31.48
Single Chip Computer
3V to 400V regulated inverter for Geiger counters | 2206 Views | Rate 16.84
3V to 400V regulated inverter for Geiger counters
Electric Fence - 20KV pulses for perimeter defense | 13864 Views | Rate 11.8
Electric Fence - 20KV pulses for perimeter defense

   

News & Updates


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

2014-10-17, Single Chip Computer

 

  

Android Custom Complex Listview with Header (no XML)


By Radu Motisan Posted on February 1st, 2011 , 1794 Views (Rate 1.29)



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:

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

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:

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

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:

  1.  
  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>
  8.  

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

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

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

  1.  
  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. }
  10.  

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:

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

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



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

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:

  1.  
  2. m_lv.setSelection(1);
  3.  

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):

  1.  
  2. m_lv = new ListView(this);
  3.  
  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;
  11.  
  12. int items = 0;
  13.  
  14. lvItem = new CustomAdapterItem( "Radu", "Motisan", idLVFirstItem+items);
  15. m_lvItems.add(lvItem);
  16. items++;
  17.  
  18. lvItem = new CustomAdapterItem( "PocketMagic", ".net", idLVFirstItem+items);
  19. m_lvItems.add(lvItem);
  20. items++;
  21.  
  22. lvItem = new CustomAdapterItem( "Complex", "Listview", idLVFirstItem+items);
  23. m_lvItems.add(lvItem);
  24. items++;
  25.  
  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. }
  31.  
  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);
  44.  

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:

  1.  
  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);
  16.  

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:
CustomComplexListview

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



More on PocketMagic:

Bluetooth and iOS - Use Bluetooth in your iPhone apps | 7403 Views | Rate 8.58
Bluetooth and iOS - Use Bluetooth in your iPhone apps
How to set the AVR Fusebits | 5281 Views | Rate 8.45
How to set the AVR Fusebits
Discussing security in online on TV News show | 2177 Views | Rate 7.48
Discussing security in online on TV News show
Atmega8 and Nokia 5110 LCD  | 4319 Views | Rate 7.23
Atmega8 and Nokia 5110 LCD
Google Tango Hackathon in Timisoara | 1486 Views | Rate 7.18
Google Tango Hackathon in Timisoara
Programmatically Injecting Events on Android - Part 1 | 6729 Views | Rate 7.15
Programmatically Injecting Events on Android - Part 1

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

  1. 1
    Sapna:

    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
    ragav:

    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.