PocketMagic

PocketMagic

Where Technology meets magic


Android
51 Posts
BlackBerry
6 Posts
Electronics
82 Posts
Hardware
139 Posts
High Voltage
56 Posts
Image processing
5 Posts
iPhone
4 Posts
Linux
2 Posts
Nuclear
26 Posts
Optics
11 Posts
Photography
7 Posts
Photoshop
3 Posts
Research
20 Posts
Reviews
18 Posts
Robotics
8 Posts
Security
9 Posts
Software
88 Posts
Symbian
2 Posts
Tubes
23 Posts
Windows Mobile
11 Posts

Sponsored Links


   

Top Articles!


Bluetooth and iOS - Use Bluetooth in your iPhone apps | 58094 Views | Rate 90.07
Bluetooth and iOS - Use Bluetooth in your iPhone apps
Simple Switched power Supplies | 59435 Views | Rate 82.43
Simple Switched power Supplies
AVR SDCard FAT support with FatFS | 17289 Views | Rate 65.74
AVR SDCard FAT support with FatFS
Programmatically Injecting Events on Android - Part 1 | 41058 Views | Rate 56.79
Programmatically Injecting Events on Android - Part 1

   

News & Updates


2014-04-15, Electric Fence Circuit for perimeter protection

2014-03-28, Infused™ project

2014-03-28, Discussing security in online on TV News show

2014-03-20, Global radiation monitoring network

 

  

Android Custom Complex Listview with Header (no XML)


By Radu Motisan Posted on February 1st, 2011 , 8993 Views (Rate 7.65)



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:

Atmega8 and enc28J60 for ethernet support | 27743 Views | Rate 43.97
Atmega8 and enc28J60 for ethernet support
Using FS1000A/XY-FST RF Radio module with AVRs | 10887 Views | Rate 40.93
Using FS1000A/XY-FST RF Radio module with AVRs
A 3D Carousel View for Android | 12434 Views | Rate 39.73
A 3D Carousel View for Android
Android Bluetooth controlled robot - Part 1 | 45863 Views | Rate 36.14
Android Bluetooth controlled robot - Part 1
How to set the AVR Fusebits | 14359 Views | Rate 35.19
How to set the AVR Fusebits
Global radiation monitoring network | 9828 Views | Rate 34.36
Global radiation monitoring network

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.

Please copy the string 0WaKcW to the field below: