Friday, March 22, 2013

Smooth Scrolling List/TableView for Titanium Android

For those who have been using the Titanium TableView UI to render lists, you may have noticed that there is a significant lag on the scroll animation when the number of list items are increased. Most of the time, if there are images on the row, the list becomes choppy and sometimes the application crashes (especially on android).  Since most of the solutions I found only adds minimal improvement on the performance, I just accepted this issue as unresolvable until a titanium sdk update handles this.

However, after using different titanium views for a while, I accidentally discovered a viable alternative to the TableView. After seeing WebViews render lists containing a lot of items with ease, I realized that I can use it as a substitute for my TableViews.

To create a "ListView" type of UI on the WebView, I used the html Table on the code like below: (Please note that I have used Mustache for rendering the data on the html template)

1:  <table border="0" style="width:100%;">  
2:                 {{#table_rows}}  
3:                 <tr onclick="Ti.App.fireEvent('app:handleRowSelect', { index : '{{row_index}}' })">  
4:                      <td>  
5:                           <img src="{{{image_url}}}" style="width:320px; height:240px; position:relative; left:10px; top:5px;"/>  
6:                      </td>  
7:                 </tr>  
8:                 {{/table_rows}}  
9:  </table>   

As you can seen on the code, I just used styles to make the rows look like a list on a TableView.  You can also see that I am firing an event whenever a row is clicked. I'll explain later how it is used.. Here is what the views look like when running on Android tablet:



You can make them look almost exactly the same so the user wouldn't notice that you are indeed using only a WebView instead of a ListView on android.

To simulate the TableView "click" event handler, you must declare an event handler on your application to capture the event fired from your html:

1:  function handleRowSelect(e) {  
2:   alert('You have selected the row with index ' + e.index);  
3:  }  
4:    
5:  Ti.App.addEventListener('app:handleRowSelect', handleRowSelect);  

Whenever the app:handleRowSelect is fired from the HTML, the handleRowSelect function will be called and the event data will be passed as parameters to this function. From the HTML code above, the   Event is fired with an object that contains the index of the row: Ti.App.fireEvent('app:handleRowSelect', { index : '{{row_index}}' }) and from this, you will be able to perform any operation on the data corresponding to the row selected.

You can try and see for yourself the huge performance improvement from using the WebView for large lists on android from here

3 comments:

  1. Hi cbpbenitez,

    have you ever tried it with remote images? I am now facing the problem that when I load data from server (json, xml) and need to show remote image instead of local image the scrolling is not smooth at all and app begin to be unusable.

    Have you faced this problem sometime?

    ReplyDelete
  2. Hi,

    I havent tried to directly display remote images in any of the apps I have implemented before. Often, when dealing with non-local images, I cache them first before displaying them on the application since loading them again on the view would indeed take a lot of memory and time.

    ReplyDelete