Fancy ListViews, Part Four PDF Print E-mail

In our last episode, we took a closer look at the ViewHolder/ViewWrapper pattern for making ListViews that much more efficient to render. Today, we switch gears, and take a look at having interactive elements in ListView rows. Specifically, we’ll look at a crude implementation of a checklist: a ListView of CheckBoxes.

The Android M5 SDK lacks any sort of checklist component. Rumors abound that the next SDK will. So, if you’re reading this, and you’re looking for a checklist, and a newer SDK is available, check the SDK — you are probably better off using the SDK’s built-in checklist than the techniques I am showing here.

That being said, while this ListView uses CheckBoxes, many of the same concepts hold true if you have a ListView whose rows hold Buttons, or perhaps an EditView.

A checklist widget is designed to allow users to easily multi-select from a list, particularly in cases where multiple selections are the norm (versus some list where multiple selections are possible but unlikely). The list contains one checkbox per row, and the user can check off those of interest:

A simple checklist view

For today’s demo, we’ll use the same basic classes as our previous demo — we’re showing a list of nonsense words, in this case as checkboxes. When the user checks a word, though, the word is put in all caps:

The same checklist, with an item checked

It’s not the most sophisticated demo on the planet, but it will keep the extraneous logic to a minimum, so we can focus on the key topics of interest.

What gets tricky with checklists is taking action when the checkbox state changes (e.g., an unchecked box is checked by the user). We need to store that state somewhere, since our CheckBox widget will be recycled when the ListView is scrolled. We need to be able to set the CheckBox state based upon the actual word we are viewing as the CheckBox is recycled, and we need to save the state when it changes so it can be restored when this particular row is scrolled back into view.

What makes this interesting is that, by default, the CheckBox has absolutely no idea what model in the ArrayAdapter it is looking at. After all, the CheckBox is just a widget, used in a row of a ListView. We need to teach the rows which model they are presently displaying, so when their checkbox is checked, they know which model’s state to modify.

So, with all that in mind, let’s look at some code. Here is the activity class, with some significant changes from the previous one:

 
  1. public class ChecklistDemo extends ListActivity { 
  2.     TextView selection; 
  3.     String[] items={"lorem", "ipsum", "dolor", "sit", "amet"
  4.                     "consectetuer", "adipiscing", "elit", "morbi", "vel"
  5.                     "ligula", "vitae", "arcu", "aliquet", "mollis"
  6.                     "etiam", "vel", "erat", "placerat", "ante"
  7.                     "porttitor", "sodales", "pellentesque", "augue"
  8.                     "purus"}; 
  9.  
  10.     @Override 
  11.     public void onCreate(Bundle icicle) { 
  12.         super.onCreate(icicle); 
  13.         setContentView(R.layout.main); 
  14.  
  15.         ArrayList list=new ArrayList(); 
  16.  
  17.         for (String s : items) { 
  18.             list.add(new RowModel(s)); 
  19.         } 
  20.  
  21.         setListAdapter(new CheckAdapter(this, list)); 
  22.         selection=(TextView)findViewById(R.id.selection); 
  23.     } 
  24.  
  25.     private RowModel getModel(int position) { 
  26.         return(((CheckAdapter)getListAdapter()).getItem(position)); 
  27.     } 
  28.  
  29.     public void onListItemClick(ListView parent, View v, int position, long id) { 
  30.         selection.setText(getModel(position).toString()); 
  31.     } 
  32.  
  33.     class CheckAdapter extends ArrayAdapter { 
  34.         Activity context; 
  35.  
  36.         CheckAdapter(Activity context, ArrayList list) { 
  37.             super(context, R.layout.row, list); 
  38.  
  39.             this.context=context; 
  40.         } 
  41.  
  42.         public View getView(int position, View convertView, ViewGroup parent) { 
  43.             View row=convertView; 
  44.             ViewWrapper wrapper; 
  45.             CheckBox cb;                                     
  46.  
  47.             if (row==null) { 
  48.                 ViewInflate inflater=context.getViewInflate(); 
  49.  
  50.                 row=inflater.inflate(R.layout.row, null, null); 
  51.                 wrapper=new ViewWrapper(row); 
  52.                 row.setTag(wrapper); 
  53.                 cb=wrapper.getCheckBox(); 
  54.  
  55.                 CompoundButton.OnCheckedChangeListener l=new CompoundButton.OnCheckedChangeListener() { 
  56.                     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
  57.                         Integer myPosition=(Integer)buttonView.getTag(); 
  58.                         RowModel model=getModel(myPosition); 
  59.  
  60.                         model.isChecked=isChecked; 
  61.                         buttonView.setText(model.toString()); 
  62.                     } 
  63.                 }; 
  64.  
  65.                 cb.setOnCheckedChangeListener(l); 
  66.             } 
  67.             else
  68.                 wrapper=(ViewWrapper)row.getTag(); 
  69.                 cb=wrapper.getCheckBox(); 
  70.             } 
  71.  
  72.             RowModel model=getModel(position); 
  73.  
  74.             cb.setTag(new Integer(position)); 
  75.             cb.setText(model.toString()); 
  76.             cb.setChecked(model.isChecked); 
  77.  
  78.             return(row); 
  79.         } 
  80.     } 
  81.  
  82.     class RowModel { 
  83.         String label; 
  84.         boolean isChecked=false
  85.  
  86.         RowModel(String label) { 
  87.             this.label=label; 
  88.         } 
  89.  
  90.         public String toString() { 
  91.             if (isChecked) { 
  92.                 return(label.toUpperCase()); 
  93.             } 
  94.  
  95.             return(label); 
  96.         } 
  97.     } 

Specifically, here is what’s new:

  1. While we are still using String[] items as the list of nonsense words, rather than pour that String array straight into an ArrayAdapter, we turn it into a list of RowModel objects. RowModel is this demo’s poor excuse for a mutable model: it holds the nonsense word plus the current checked state. In a real system, these might be objects populated from a Cursor, and the properties would have more business meaning.

  2. Utility methods like onListItemClick() had to be updated to reflect the change from a pure-String model to use a RowModel.

  3. The ArrayAdapter subclass (CheckAdapter), in getView(), looks to see if convertView is null. If so, we create a new row by inflating a simple layout (see below) and also attach a ViewWrapper (also below). For the row’s checkbox, we add an anonymous onCheckedChanged() listener that looks at the row’s tag (getTag()) and converts that into an Integer, representing the position within the ArrayAdapter that this row is displaying. Using that, the checkbox can get the actual RowModel for the row and update the model based upon the new state of the checkbox. It also updates the text of the CheckBox when checked to match the checkbox state.

  4. We always make sure that the CheckBox has the proper contents and has a tag (via setTag()) pointing to the position in the adapter the row is displaying.

The row layout is very simple: just a CheckBox inside a LinearLayout:

 
  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="fill_parent" 
  4.     android:layout_height="wrap_content" 
  5.     android:orientation="horizontal" 
  6. > 
  7.     <CheckBox 
  8.         android:id="@+id/check" 
  9.         android:layout_width="wrap_content" 
  10.         android:layout_height="wrap_content" 
  11.         android:text="" /> 
  12. </LinearLayout> 

Arguably, the LinearLayout is superfluous, but I left it in to remind you that the rows could be more complicated than just a CheckBox — you might have some ImageViews with icons depicting various bits of information about the row, for example.

The ViewWrapper is similarly simple, just extracting the CheckBox out of the row View:

 
  1. class ViewWrapper { 
  2.     View base; 
  3.     CheckBox cb=null
  4.  
  5.     ViewWrapper(View base) { 
  6.         this.base=base; 
  7.     } 
  8.  
  9.     CheckBox getCheckBox() { 
  10.         if (cb==null) { 
  11.             cb=(CheckBox)base.findViewById(R.id.check); 
  12.         } 
  13.  
  14.         return(cb); 
  15.     } 

This is a fairly cumbersome bit of code. No doubt it can be simplified directly, such as by directly holding the RowModel in the tag versus an Integer pointing inside the ArrayAdapter. In addition, in a later episode of this blog post series, we’ll see how you can wrap much of the complexity up into a CheckList custom widget, so you do not have to keep repeating this code every place you want a checklist.

 

Source: http://androidguys.com/2008/07/25/fancy-listviews-part-four/

Comments (18)Add Comment
birkenstock shoes
written by birkenstock , May 29, 2010
When you are on a holiday in some seaside resort where you will hike and walk on cliffs, Birckenstock is one of the brands to which you turn your attention to find some slippers or flip-flops that make a holiday in comfort and without pain in the feet after a romantic walk on the rocks.Birkenstocks is the well-known German footwear brand: Birkenstock shoes, Birkenstock sandals and Birkenstock clogs.Birkenstock Gizeh is a flattering flip-flop style with a leather upper that will look great with shorts, jeans or dresses, at the same time, it has an irresistible air between the tourist and hiking, and you can be sure that the evening will have no pain, given the high quality these shoes.
report abuse
vote down
vote up
Votes: +0
air max 2009
written by air max 2009 , May 31, 2010
are you looking for a air max 2009?
here are not only offer the nike free shoes ,but aslo for thenew lebron VII shoes
report abuse
vote down
vote up
Votes: +0
...
written by mbt , June 18, 2010
While in this case we added new tabs based on button clicks
report abuse
vote down
vote up
Votes: +0
...
written by authentic jordans , June 18, 2010
thanks for your post!!!!!!!!!
report abuse
vote down
vote up
Votes: +0
What makes this ...
written by coach handbag , June 19, 2010
What makes this interesting is that, by default, the CheckBox has absolutely no idea what model in the ArrayAdapter it is looking at. After all, the CheckBox is just a widget
report abuse
vote down
vote up
Votes: +0
Cheap San Francisco 49ers Jerseys
written by sexy bikinis , June 24, 2010
It is not the NFL Jerseys critic who counts,not the man who points out how the strong man stumbles,the doer of deeds could have sexy bikinis sale done them better. The credit belongs to the man who is actually in the arens,whose face is marred by dust and sweat and blood.
report abuse
vote down
vote up
Votes: +0
Uggs Sale
written by Uggs Sale , June 26, 2010
ugg boots shop offer powerful training shoes ,Tall ugg shoes
report abuse
vote down
vote up
Votes: +0
...
written by Ugg Boots UK , June 26, 2010
Wow - really powerful post. Thanks for taking time to share this personal perspective that not only we as individuals should heed, but organizations as well. Ugg Boots UK becoming more and more popular,new style Ugg Boots will be the best seller for this Christmas
report abuse
vote down
vote up
Votes: +0
uggs shoes
written by uggs shoes , June 26, 2010
Thanks for sharing ,really helped a lot here! We are the best and professional online retailer, offering top quality Classic uggs sale, Short ugg boots and free shipping worldwide
report abuse
vote down
vote up
Votes: +0
goedkope uggs
written by goedkope uggs , June 26, 2010
We are shortly launching our new website,http://www.uggofficial.nl/ which will focus on selling ugg boots
report abuse
vote down
vote up
Votes: +0
uggs boots
written by uggs boots , June 26, 2010
Thank you again for all the knowledge you distribute,Nowadays,people pay more attention to high quality life style. High quality means ,comfortable and healthy, very useful womens ugg boots is very popular now.Made from sheepskin, bailey button uggs is very comfortable and warm
report abuse
vote down
vote up
Votes: +0
...
written by vibram shoes , June 26, 2010
I agree you! excellent review!vibram five fingers have been popular for a long time,for its excellent quality and further features,I’ve always wanted to have a pair of beauty fivefingers running shoes
report abuse
vote down
vote up
Votes: +0
...
written by ed hardy sale , June 26, 2010
Thanks for sharing !So nice to see you !I will buy a wallet for my best friend! Shopping Cheap EdHardy can be used on various occasions and in different ways. Do you know all these? It’s the time for you to know; It is true that everyone wants to wear the latest trend and wish to buy that pair which is in heavy demand. But it would be better to check what kind of ed hardy clothing that you love
report abuse
vote down
vote up
Votes: +0
...
written by hollister , June 26, 2010
I really love your website, it's so useful, i'm just sharing for my friends!Strong winter weather is hitting most of the United States right now. Many of the states that are not used to seeing even the slightest amount of snow, are being bombarded with strong winter weather. If you want to keep warm in this winter
you might try adding some clothes to your inventory like abercrombie & fitch clothing
report abuse
vote down
vote up
Votes: +0
mbt
written by mbt shoes , June 29, 2010
.Many of the states that are not used to seeing even the slightest amount of snow, are being bombarded with strong winter weather. If you want to keep warm in this winter .
ugg boots
report abuse
vote down
vote up
Votes: +0
That was awesome!
written by review my resume , July 07, 2010
This article is really informativem thank you for usefull stuff
report abuse
vote down
vote up
Votes: +0
...
written by christian louboutin shoes , July 08, 2010
Everyone can buy christian louboutin
christian louboutin shoes on our shop ,We provide lots of lady shoes here.
report abuse
vote down
vote up
Votes: +0
...
written by Abercrombie and fitch , July 29, 2010
http://whyandroid.com/android/...cator.html
report abuse
vote down
vote up
Votes: +0

Write comment
quote
bold
italicize
underline
strike
url
image
quote
quote
smile
wink
laugh
grin
angry
sad
shocked
cool
tongue
kiss
cry
smaller | bigger

security code
Write the displayed characters


busy
 

 

This domain is for sale! Please contact me via contact page!