Monday, March 12, 2012

Tables and cell selections: iOS UITableView vs Android ListView



One of the first things every dev learns when he/she starts developing on a mobile platform is how to present sets of data. They could be a list of shops, an array of products and so on.
Both Android and iOS have a component to manage this kind of data: ListView for the former, and UITableView for the latter.

These classes surprisingly offer a similar interface, and have similar ways to provide the datasource to it.

Both platforms have a component to show the elements on screen and a datasource (or adapter) that manages the presentation of the tableview cells, the cells reuse and how data are presented (in which order).

iOS has a protocol, UITableViewDataSource, that every class that wants to provide some data to a UITableView must implement. The key method used to provide the tableView cells is

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

On the other side, Android datatsource is a class that extends ListAdapter.
Also this class has a method that must be always implemented:

public View getView (int position, View convertView, ViewGroup parent) 


In both platforms it is very important to reuse the cells: with iOS 5 the cell recycle is managed by the system, in case the cell is declared in the .xib file as the default subview of the UITableView. It is very important though to specify a cell-id in code that matches the one declared in the .xib file.


Android use a system quite similar to that used by iOS 4.x and lower. You fetch a view inflating it from an xml file only if the view provided by the framework is null (i.e. there isn't currently a reusable cell).


This is a typical iOS 5.0 implementation:



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellId"];
    cell.textLabel.text = [_list objectAtIndex:indexPath.row];
    cell.selectionStyle = UITableViewCellSelectionStyleGray;
   
    return cell;
}


While this one is an Android implementation of getView():



public View getView (int position, View convertView, ViewGroup parent){
    LinearLayout layout;
    if(convertView == null){
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(LAYOUT_INFLATER_SERVICE);
    layout = (LinearLayout)inflater.inflate(R.layout.cellnull);
    }
    else{
    layout = (LinearLayout)convertView;
    }
    
   ((TextView)layout.findViewById(R.id.cell_title)).setText(dataSource.get(position));
    
    return layout;
    }

The highlithed row shows the comparision made to establish if a convertView is available. If not, it is inflated from the XML layout file.

Another important issue to face is how to customize the list selector.
In iOS it is a very straightforward procedure: just specify the selection style, or if you want a different color, create a background view with the color you want as its background and assign it to the selectedBackgroundView property (see: http://stackoverflow.com/questions/1998775/uitableview-cell-selected-color).

On Android, a premise is necessary. Every component (button, tetview, and also cell views) has different states that define how the rendering engine should show them on screen. The states are: pressed, focused, selected, enabled.
Concerning the ListView component, the system provides a way to select cells that is specified by a property called listSelector. The listSelector is an xml file with a set of rules, similar to the rules you specify on a css web page, that define how an item is shown in a set of possible states.
I've found very difficult to customize this behavior. Every time I tried to customize the cell selection appeareance, I came across many different issues: some times the selection changed the appeareance of all the tableview items, some other times the cell divider disappeared from screen.

In the official samples app there isn't a single example on how to customize such property, and also watching the World of ListView Google IO Session didn't helped me a lot (see link here : http://www.youtube.com/watch?v=wDBM6wVEO70 )

So I came up with a simple yet effective solution: get rid of the listSelector property by imposing a transparent view for every possible state, and by modifying the background of the cell items instead.

This is the selector I've used:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!--    <item android:drawable="@color/test_color" android:state_pressed="true" android:state_selected="true"></item> -->
<!--     <item android:drawable="@color/test_color" android:state_pressed="false" android:state_selected="true"></item> -->
    <item android:drawable="@color/test_color" android:state_pressed="true" android:state_selected="false"></item>
    <item android:drawable="@color/black" android:state_pressed="false" android:state_selected="false"></item>
</selector> 

You can also uncomment the first two rows if you want to manage the selected state (it is useful if your device has a D-Pad).









5 comments:

  1. Excellent work.I am very pleased on you by read your blog detail.Nice to read this post.
    Android app developers

    ReplyDelete
  2. Thanks For sharing this code. Check this only android code.

    it is useful for us.

    http://devappandroid.com/android-beginner/iphone-uitable-view-android

    ReplyDelete
  3. Yeah, this is really annoying on Android. The settings screen in Android seems to have the grouped style headings of a UITableView however this is not part of the ListView functionality by default.

    The way I did it was to add a separate view into the ListView row which had the title and underline, and then to programmatically show and hide it when it was needed.

    Pretty annoying but it works.

    Also we just released PortKit: UX Metaphor Equivalents for iOS & Android

    http://kintek.com.au/blog/portkit-ux-metaphor-equivalents-for-ios-and-android/

    It has side by side comparisons of the native ui widgets and links to downloadable PSDs for designing.

    ReplyDelete
  4. Nice information. I was searching for the same. It helped me alot and saved my time. Thanks a lot.
    website design melbourne | SEO services Melbourne

    ReplyDelete