Wednesday, February 2, 2011

Appcelerator Titanium Scrollview Swipe functionality

I have recently started looking into the development of Appcelerator titanium for iphone and ipad. I have been finding the tool great for RAD development of mobile applications. The major problem i have faced with this platform is the memory management stuff. The inbuilt memory management is something quite unsatisfactory. Today I am going to discuss one such problem that I faced with appcelerator.

I wanted to have a simple functionality of swiping through the images in appcelerator, something that is very common in appcelrator. So I decided to use the most obvious choice ScrollableView. But on using the scrollableview the memory started shouting since I had approximately 150 - 200 images. Now the question was how to do this, I spent around 4 days searching blogs and all, but no answers. So I decided to find a solution.

The simplest logical answer was to have three imageviews in the scrollview each at index 0, 1, 2. The image displayed on the screen is always at index 1. Now on the swipe of right to left you should remove the view at position 0 and assign the view at position 1 to position 0, the view at position 2 to position 1 and the view that was at position 0 to position 2 and provide the view with new image. Similarly follow the reverse case for swiping form left to right. Attached is my code of App.js

// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');

//
// create base UI tab and root window
//
var win1 = Titanium.UI.createWindow({
title:'Tab 1',
backgroundColor:'#fff'
});

var imageViewArray = [];
var imageNameArray = [];
var nextImageIndex;

for(var i = 0; i < 3 ; i++){
var imageView1 = Titanium.UI.createImageView({
//image: imagePath
});
imageViewArray[i] = imageView1;
}


var scrollingView = Titanium.UI.createScrollableView({
//contentWidth:1280,
//contentHeight:450,
views:imageViewArray,
width: 310,
height: 450,
top: 5,
left: 5,
borderWidth: 2,
borderColor: '#000'
});

scrollingView.addEventListener('scroll', function(e){
Ti.API.info("C=" + e.currentPage);
Ti.API.info("N=" + nextImageIndex);
if(e.currentPage == 2 && nextImageIndex < imageNameArray.length - 2)
{
//Setting the current page to 1 will allow the smooth swipe functionality
scrollingView.currentPage = 1;
nextImageIndex += 1;
var vw = scrollingView.views[0];
imageViewArray[0] = scrollingView.views[1];
imageViewArray[1] = scrollingView.views[2];
scrollingView.removeView[vw];
vw.image=imageNameArray[nextImageIndex + 1];
imageViewArray[2] = vw;
scrollingView.views = imageViewArray;
}
else if(e.currentPage == 0 && nextImageIndex > 1)
{
nextImageIndex -= 1;
scrollingView.currentPage = 1;
var vw = scrollingView.views[2];
imageViewArray[1] = scrollingView.views[0];
imageViewArray[2] = scrollingView.views[1];
scrollingView.removeView[vw];
vw.image=imageNameArray[nextImageIndex - 1];
imageViewArray[0] = vw;
scrollingView.views = imageViewArray;
}
});

//get the config from config.xml
/*
Sample xml nodes
<root>
<items>
<item>True-Blood.jpg</item>
<item>2219-true-blood.jpg</item>
<item>true-blood-20080905051323782_640w.jpg</item>
</items>
</root>
*/
var f = Titanium.Filesystem.getFile(Titanium.Filesystem.resourcesDirectory, '320x480/images.xml');
var contents = f.read();
var xmlObject = Ti.XML.parseString(contents.text);
var imageNode = xmlObject.documentElement.getElementsByTagName("item");

for(var i = 0; i < imageNode.length; i++)
{
var imagePath = '320x480/' + imageNode.item(i).text;
imageNameArray[i] = imagePath;
}

scrollingView.views[0].image = imageNameArray[0];
scrollingView.views[1].image = imageNameArray[1];
scrollingView.views[2].image = imageNameArray[2];
nextImageIndex = 1;


win1.add(scrollingView);
win1.open();


I believe this is an alternative to the memory leak. Appcelerator team should provide the ultimate solution to this problem.

Please let me know if you find any issues with this. If my post helps you, dont forget to thank me ;)

Enjoy Coding

Shakil Bharucha

14 comments:

RealWorldSoftware said...

looks alot like this solution https://gist.github.com/810171

Daniel said...

Thanks... this is a nice solution

ToM04 said...

look nice but how can you integrate an orientation change, that you can view landscape too?

King Of**Rainbow said...

Hi Shakil,

Just came up with a solution to any memory problems. See here: http://developer.appcelerator.com/question/116867/this-is-a-solution-to-your-memory-woes

Rey Jexter Bumalay said...

This is a nice article but I'm having problem with flickering in ipad.

Adam Campbell said...

@Rey: In my code, I put

scrollingView.currentPage = 1;

as the last thing to happen. It isn't perfect, but reduces flashes maybe 80%.

mboro said...

Working solution to the iPad flickering:

The use of the removeView method is being used incorrectly. It should be removeView( vw ); instead of removeView[vw];

Also, just remove the currentPage = 1; in the two conditions and put in at the bottom of the function like Adam is suggesting. This fixes it for me :-)

VDS said...

Good work.
It flickr a little bit when scrolling to the left but it's ok.
I have to display the imageView plus a label showing the image name, but for this I have to know the "real" index of the image in the scroll event.
How can I get it ?
Thanks

Denis said...

if the size of images is not too large, try cacheSize of scrollview :) everything else is unnecessary. 6 hours of headache

Nikunj Kapupara said...

Hi..

I want to know that is Scrollable view can display circular view .

Means when user at last view at that time he swipe it will display first view..

Thanks

samir said...

Is it possible that we can manage 5 images instead of 3 images at a time.

ekjyot kaur said...

Hi
I have implemented this code for sliding images. Its working pretty fine.
But i do have 1 more concern.
i am placing the images in an array.
And if i want to come back to same screen with some random image of the array. I want it should have the previous and next images of the array,
sliding,
But the problem that i am facing is that i am able to scroll to next images but previous images dont come as i set the image of 1st view as that random image. So how can i resolve this problem.

ekjyot kaur said...
This comment has been removed by the author.
George Gerald Mendoza said...

Hi all,

Has anyone found a solution on the flickering?

Thanks