Issue
Not able to longer scroll the tableView all the way to the bottom, when attempt animating the 'top' value of a tableView, causes it the contentView to stop scrolling correctly on iOS.
Reproducible steps
* 1. Start the app! :)
* 2. Scroll the tableView up/down to make sure that all rows are visible
* 3. Click on the blue bar (Where it says 'Click me!')
* 4. Attempt to scroll the tableView all the way to the bottom
* 5. Click on the blue bar
* 6. Attempt to scroll the tableView (after it is now in its original state)
This happens after step 4, and then step 6 will return the table to its original state, where you are still unable to scroll to the bottom.
Expected
Scroll tableView as needed
Actual
You can scroll the entire tableView, only once, when actually the application is first launched.
Tested on
iOS 6 simulator
iPhone 4 - iOS 6
Console output
[WARN] New layout set while view [object TiUITableView] animating: Will relayout after animation.
Runnable sample
var platformHeight = Ti.Platform.displayCaps.platformHeight - 20, //status bar
platformWidth = Ti.Platform.displayCaps.platformWidth;
var fullsizeContainer = Ti.UI.createAnimation({height: platformHeight, duration: 300});
var halfsizeContainer = Ti.UI.createAnimation({height: platformHeight/2, duration: 300})
var showGreenBar = Ti.UI.createAnimation({top: 60, duration: 300});
var hideGreenBar = Ti.UI.createAnimation({top: 20, duration: 300});
var TABLESTATE = {half: 1, full: 2};
(function() {
var appWindow = Ti.UI.createWindow({
backgroundColor:'white'
});
var container = Ti.UI.createView({
backgroundColor: 'white',
height: platformHeight/2,
width: platformWidth,
bottom: 0
});
var blueBar = Ti.UI.createLabel({
backgroundColor: 'blue',
text: "Click Me!",
color: 'white',
width: platformWidth,
height: 20,
top: 0,
textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER,
borderColor: 'black' //for aesthetics
});
var greenBar = Ti.UI.createView({
backgroundColor: 'green',
width: platformWidth,
height: 40,
top: 20
});
var tableData = [];
var sectionOne = Ti.UI.createTableViewSection({
headerTitle: "Section One"
});
var sectionTwo = Ti.UI.createTableViewSection({
headerTitle: "Section Two"
});
for(var i = 0; i < 20; i++){
var row = Ti.UI.createTableViewRow({
title: "Example Row"
});
if(i%2){
sectionOne.add(row);
} else {
sectionTwo.add(row);
}
}
tableData.push(sectionOne);
tableData.push(sectionTwo);
var tableView = Ti.UI.createTableView({
backgroundColor: 'white',
height: Ti.UI.FILL,
width: platformWidth,
top: 20,
data: tableData,
borderColor: 'red'
});
var tableState = TABLESTATE.half;
blueBar.addEventListener('click', function(e){
if(tableState === TABLESTATE.half){
//goes from half --> full
container.animate(fullsizeContainer);
tableView.animate(showGreenBar);
tableState = TABLESTATE.full;
} else {
//goes from full --> half
tableView.animate(hideGreenBar);
container.animate(halfsizeContainer);
tableState = TABLESTATE.half;
}
});
container.add(blueBar);
container.add(greenBar);
container.add(tableView);
appWindow.add(container);
appWindow.open();
})();
iOS does not support nesting animations. Need to run animations one after the other. Use sample code below
var platformHeight = Ti.Platform.displayCaps.platformHeight - 20, //status bar platformWidth = Ti.Platform.displayCaps.platformWidth; var fullsizeContainer = Ti.UI.createAnimation({height: platformHeight, duration: 300}); var halfsizeContainer = Ti.UI.createAnimation({height: platformHeight/2, duration: 300}) var showGreenBar = Ti.UI.createAnimation({top: 60, duration: 300}); var hideGreenBar = Ti.UI.createAnimation({top: 20, duration: 300}); var TABLESTATE = {half: 1, full: 2}; (function() { var appWindow = Ti.UI.createWindow({ backgroundColor:'white' }); var container = Ti.UI.createView({ backgroundColor: 'white', height: platformHeight/2, width: platformWidth, bottom: 0 }); var blueBar = Ti.UI.createLabel({ backgroundColor: 'blue', text: "Click Me!", color: 'white', width: platformWidth, height: 20, top: 0, textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER, borderColor: 'black' //for aesthetics }); var greenBar = Ti.UI.createView({ backgroundColor: 'green', width: platformWidth, height: 40, top: 20 }); var tableData = []; var sectionOne = Ti.UI.createTableViewSection({ headerTitle: "Section One" }); var sectionTwo = Ti.UI.createTableViewSection({ headerTitle: "Section Two" }); for(var i = 0; i < 20; i++){ var row = Ti.UI.createTableViewRow({ title: "Example Row "+i }); if(i%2){ sectionOne.add(row); } else { sectionTwo.add(row); } } tableData.push(sectionOne); tableData.push(sectionTwo); var tableView = Ti.UI.createTableView({ backgroundColor: 'white', height: Ti.UI.FILL, width: platformWidth, top: 20, data: tableData, borderColor: 'red' }); var fullsizeHandler = function() { fullsizeContainer.removeEventListener('complete',fullsizeHandler); tableView.animate(showGreenBar); }; var halfsizeHandler = function() { halfsizeContainer.removeEventListener('complete',halfsizeHandler); tableView.animate(hideGreenBar); }; var tableState = TABLESTATE.half; blueBar.addEventListener('click', function(e){ if(tableState === TABLESTATE.half){ //goes from half --> full fullsizeContainer.addEventListener('complete',fullsizeHandler); container.animate(fullsizeContainer); tableState = TABLESTATE.full; } else { //goes from full --> half halfsizeContainer.addEventListener('complete',halfsizeHandler); container.animate(halfsizeContainer); tableState = TABLESTATE.half; } }); container.add(blueBar); container.add(greenBar); container.add(tableView); appWindow.add(container); appWindow.open(); })();Understood, the 'Complete' event listener fixes the TableView scrolling issue however animation its not quite the look the developer was attempting to make with those animations. Attaching a native sample that performs the nested Animation:
Attached files
- *TableViewTest.zip* native sample project _Animation block_ in ContainerViewController.m- (void) toggleTable { if(half){ [UIView beginAnimations:@"animateFull" context:nil]; [UIView setAnimationDuration:0.2]; [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; [[containerView view] setFrame:CGRectMake(0, 0, 320, [[UIScreen mainScreen] bounds].size.height)]; [blueButton setFrame:CGRectMake(0, 0, 320, 20)]; [greenBar setFrame:CGRectMake(0, 20, 320, 60)]; [[tableViewController tableView] setFrame:CGRectMake(0, 80, 320, [[UIScreen mainScreen] bounds].size.height - 80)]; [UIView commitAnimations]; half = false; } else { [UIView beginAnimations:@"animateHalf" context:nil]; [UIView setAnimationDuration:0.2]; [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; [[containerView view] setFrame:CGRectMake(0, [[UIScreen mainScreen] bounds].size.height/2, 320, [[UIScreen mainScreen] bounds].size.height/2)]; [blueButton setFrame:CGRectMake(0, [[UIScreen mainScreen] bounds].size.height/2 - 20, 320, 20)]; [greenBar setFrame:CGRectMake(0, [[UIScreen mainScreen] bounds].size.height/2 + 20, 320, 60)]; [[tableViewController tableView] setFrame:CGRectMake(0, [[UIScreen mainScreen] bounds].size.height/2, 320, [[UIScreen mainScreen] bounds].size.height/2 -20)]; [UIView commitAnimations]; // [[containerView view] bringSubviewToFront:[tableViewController tableView]]; half = true; } }Attached videos
- *TitaniumSample_1.mov (iPod & iPhone) 2.m4v* This is the result where animations are nested, a minimum test case was posted (without 'complete' event listener). See how Warnings are being thrown then tableView stops scrolling. - *TitaniumSample_2.mov (iPod & iPhone) 2.m4v* Result after adding a 'Complete' event listener. Fixes the scrolling issue however animates it different. - *NativeSample.mov (iPod & iPhone).m4v* Result of running a native sample where animations worked nested. Have the look the developer attempts to do.The native code is running a single animation within which two views are animated. The Titanium code is running two animations. Right now we do not support animating two views within a single animation. You can fake it by running the subview animation before the parent view animation and giving the subview view animation a extra time. Try this code instead
var platformHeight = Ti.Platform.displayCaps.platformHeight - 20, //status bar platformWidth = Ti.Platform.displayCaps.platformWidth; var fullsizeContainer = Ti.UI.createAnimation({height: platformHeight, duration: 200}); var halfsizeContainer = Ti.UI.createAnimation({height: platformHeight/2, duration: 200}) //Give the tableview animations a extra time to complete (x5) //why so much? To compensate for JS bridge and layout engine delays var showGreenBar = Ti.UI.createAnimation({top: 60, duration: 1000}); var hideGreenBar = Ti.UI.createAnimation({top: 20, duration: 1000}); var TABLESTATE = {half: 1, full: 2}; (function() { var appWindow = Ti.UI.createWindow({ backgroundColor:'white' }); var container = Ti.UI.createView({ backgroundColor: 'white', height: platformHeight/2, width: platformWidth, bottom: 0 }); var blueBar = Ti.UI.createLabel({ backgroundColor: 'blue', text: "Click Me!", color: 'white', width: platformWidth, height: 20, top: 0, textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER, borderColor: 'black' //for aesthetics }); var greenBar = Ti.UI.createView({ backgroundColor: 'green', width: platformWidth, height: 40, top: 20 }); var tableData = []; var sectionOne = Ti.UI.createTableViewSection({ headerTitle: "Section One" }); var sectionTwo = Ti.UI.createTableViewSection({ headerTitle: "Section Two" }); for(var i = 0; i < 20; i++){ var row = Ti.UI.createTableViewRow({ title: "Example Row "+i }); if(i%2){ sectionOne.add(row); } else { sectionTwo.add(row); } } tableData.push(sectionOne); tableData.push(sectionTwo); var tableView = Ti.UI.createTableView({ backgroundColor: 'white', height: Ti.UI.FILL, width: platformWidth, top: 20, data: tableData, borderColor: 'red' }); var tableState = TABLESTATE.half; blueBar.addEventListener('click', function(e){ //Run tableView animation before the container animation. if(tableState === TABLESTATE.half){ //goes from half --> full tableView.animate(showGreenBar); container.animate(fullsizeContainer); tableState = TABLESTATE.full; } else { //goes from full --> half tableView.animate(hideGreenBar); container.animate(halfsizeContainer); tableState = TABLESTATE.half; } }); container.add(blueBar); container.add(greenBar); container.add(tableView); appWindow.add(container); appWindow.open(); })();tableView is scrollable. Verified on : iPhone 5, iOS 6 SDK version: 3.1.0.v20130111163212 CLI version : 3.0.23 OS : MAC OSX 10.7.5 XCode : 4.5.1