Kah – The Developer

Adding Selection Functionality to the Table View

Posted by: kahgoh on: 29 March, 2009

Lately, I was looking at how to present data in a table format, where each row would be data from an object, and allow users to select a particular row. One way of doing it is writing a ListAdapter and using it with a ListView. However, the way I tried to do it was using the TableLayout.

Admittedly, using the TableLayout looked like it is more complicated than using the ListView, although I have yet to try using ListView. Using the TableLayout, the view is programatically created (without using an XML file). In order to implement this, the implementing class needs to keep track of a number of things.


  1 package com.android.selectable;
  2
  3 import java.util.Collection;
  4
  5 import android.content.Context;
  6 import android.graphics.Color;
  7 import android.util.Log;
  8 import android.view.MotionEvent;
  9 import android.view.View;
 10 import android.widget.TableLayout;
 11 import android.widget.TableRow;
 12
 13 /**
 14  * Manages the display of the watch list.
 15  *  
 16  * @author Kah
 17  */
 18 public class ListDisplay<T>
 19 {
 20   /**
 21   * Reference to the list of stocks that are in the
 22   * watch list.
 23   */
 24   private final Collection<T> itemsCollection;
 25   
 26   /**
 27    * Reference to the view that displays the watch
 28    * list on the user interface. This needs to
 29    * inflated later, since the instance of the
 30    * layout inflater is required to create it.
 31    */
 32   private final TableLayout display;
 33
 34   private final Context appContext;
 35
 36   private final DisplayAdapter<T> dataAdapter;
 37
 38   private SelectionReceiver<T> selectionObserver;
 39   
 40   private T highlighted;
 41   

The DisplayAdapter is used to convert the objects into the data that gets displayed. A SelectionReceiver is notified when a item is selected by clicking on it.

The constructor creates the TableLayout, which may be set as the content view or may be added to another view.
 67   /**
 68    * Retrieves the display component to display the
 69    * contents of the watch
 70    * list on the user interface.
 71    *
 72    * @return The display view for viewing the contents
 73    *         of the watch list.
 74    */
 75   public View getDisplay() 
 76   {
 77     return display;
 78   }
 79
 80   /**
 81    * Retrieves the last item that was selected, but not
 82    * necessarily "clicked".
 83    *
 84    * @return The item that is currently at the cursor.
 85    */
 86   public T getSelected() 
 87   {
 88     return highlighted;
 89   }
 90

Next, the data from the list needs to be loaded into the table. This is done by adding a series table rows. Each row needs to be made focusable. Listeners are added to row to handle the highlighting and when the user clicks on a row. For highlighting, the OnFocusChangeListener and OnTouchListener are required. Clicking is handled by OnClickListener.

 91   /**
 92    * Loads the current contents of the list to the
 93    * displayed list. 
 94    */
 95   private void initialiseDisplay() 
 96   {
 97     // All rows will have the same parameters, so just
 98     // create it once.
 99     final TableRow.LayoutParams rowParams = new 
100       TableRow.LayoutParams(
101         TableRow.LayoutParams.FILL_PARENT,
102         TableRow.LayoutParams.WRAP_CONTENT);
103     
104     
105     // Go through the list and create table entries for
106     // each one.
107     for (T item: itemsCollection) 
108     {
109       TableRow newRow = new TableRow(appContext);
110       newRow.setLayoutParams(rowParams);
111       
112       View[] content = dataAdapter.getContent(item);
113       for (int index = 0; index < content.length; index++) 
114       {
115         newRow.addView(content[index]);
116       }
117       
118       newRow.setFocusable(true);
119       newRow.setFocusableInTouchMode(true);
120       newRow.setOnFocusChangeListener(
121         new RowHighlighter(item));
122       newRow.setOnClickListener(new RowSelector(item));
123
124       display.addView(newRow);
125     }
126   }
127   

Notifications about which item the user clicks is sent via the SelectionReceiver. This is an external class that we define. Of course, there needs to be a way of setting which instance of the SelectionReceiver will receive the notification.

128   /**
129    * Changes the receiver that is notified when an item
130    * is "clicked".
131    *
132    * @param receiver
133    *      The receiver that will be notified of changes.
134    */
135   public void setSelectionReceiver(
136    SelectionReceiver<T> receiver)
137   {
138     this.selectionObserver = receiver;
139   }
140   

The definition for the highlighting class:

141   /**
142    * This focus change listener handles the changing the
143    * background colour for highlighting the focused row.
144    * It also updates the variable keeping track the
145    * highlighted item.
146    */
147   private class RowHighlighter implements 
148     View.OnFocusChangeListener, View.OnTouchListener
149   {
150
151     /**
152      * The item that the highlighter is associated with. 
153      */
154     private final T association;
155     
156     public RowHighlighter(T association) 
157     {
158       this.association = association;
159     }
160     
161     /**
162      * {@inheritDoc}
163      */
164     @Override
165     public void onFocusChange(View v, boolean hasFocus)
166     {
167       int bgColour = Color.TRANSPARENT;
168       if (hasFocus == true
169       {
170         bgColour = Color.RED;
171         highlighted = association;
172       }
173
174       v.setBackgroundColor(bgColour);
175     }
176
177     /**
178      * {@inheritDoc}
179      */
180     @Override
181     public boolean onTouch(View v, MotionEvent event)
182     {
183       if (event.getAction() != MotionEvent.ACTION_UP) 
184       {
185         v.requestFocus();
186       }
187       return false;
188     }
189     
190   }
191   

Finally, the internal class for updating the row that is selected.

192   /**
193    * Handles the "clicking" on a row.
194    *
195    * @author Kah
196    */
197   private class RowSelector implements View.OnClickListener
198   {
199     private final T association;
200     
201     public RowSelector(T association) 
202     {
203       this.association = association;
204     }
205     
206     /**
207      * {@inheritDoc}
208      */
209     @Override
210     public void onClick(View v)
211     {
212       if (selectionObserver != null) {
213         selectionObserver.itemSelected(association);
214       }
215     }
216   }
217 }
218  
219

If you wish to download the source code, you can get it from here. As mentioned previously, this seems a long way of achieving a selectable list of items with three columns. Using a ListView, the item selection and item highlighting is taken care of. But how to use ListView is left for another day.

Leave a Reply


  • sumeet inani: Hi I have installed ion3 in ubuntu 8.04.How do I start it I tried running ion3 in terminal when logged in but it says >> Unable to redirect r
  • kahgoh: Hi, The ShowProgress (this is already listed above!) class is actually the listener. You can tell because it implements the
  • ohnoezitasploded: I'm lost on the line: builder.setPositiveButton("Progress", listener); Where is listener in the code? I'm new at this so maybe if there was a com

Blog Stats

  • 34,333 hits

Pages