Animate - Strange behavior

You must Login before you can answer or comment on any questions.

I am stumped by the behavior I'm seeing when animating a stack of views in my mobile application (right now, I'm focusing on iPhone).

It's a 3-tab application, and in one of the tabs, I have the base window, with several views added to it and stacked up in the appropriate order. They are positioned off-screen, by setting their left position to '100%'. My goal was that when I want to advance in the stack, I fade out the current view (animate the opacity to 0), slide in the next view (animate the left position to 0), and set a running variable to keep track of where I am in the stack. Simple right?

It works as expected when advancing through the stack (no issues whatsoever), but when I try to go back (retreat), the previous view (the one that's supposed to be displayed after clicking "back") fades into view as expected, followed by immediately disappearing. Also, the view that was supposed to animate off to the left (sliding out of view) only slides over about a 1/3 of the screen.

Bug with Views, the animate method, the positioning properties, or am I just missing something idiotic in my own code?

Thanks in advance.

Code for the window is as follows:

(function() {
    cc.ui.createAssessWindow = function(_args) {
        var self = Ti.UI.createWindow(cc.combine($$.Window, { title: L('win-title-assess') })),
            windowStack = [],
            windowStackCurrent = 0,
            btnSelectPlayer = Ti.UI.createButton({ systemButton: Ti.UI.iPhone.SystemButton.ADD }),
            btnBack = Ti.UI.createButton({ title:'back' });
 
        //Set up the view stack here
        windowStack.push(cc.ui.createAssessView1());
        windowStack.push(cc.ui.createAssessView2());
        windowStack.push(cc.ui.createAssessView3());
        windowStack.push(cc.ui.createAssessView4());
        windowStack.push(cc.ui.createAssessView5());
        windowStack.push(cc.ui.createAssessView6());
        windowStack.push(cc.ui.createAssessView7());
        windowStack.push(cc.ui.createAssessView8());
 
        for (i=0; i<windowStack.length; i++) {
            self.add(windowStack[i]);
        }
 
        //Activate the select player button
        self.rightNavButton = btnSelectPlayer;
 
 
        //Event listeners       
        btnSelectPlayer.addEventListener('click', function(e){ 
            Ti.App.fireEvent('app:assess.stackAdvance');
        });
 
        btnBack.addEventListener('click', function(e){ 
            Ti.App.fireEvent('app:assess.stackRetreat');
        });
 
 
        //Global app event listeners
        Ti.App.addEventListener('app:assess.stackAdvance', function(e) {
            if (windowStackCurrent<windowStack.length-1) {
                var next = windowStackCurrent + 1;
                windowStack[windowStackCurrent].animate({ opacity:0, duration:$$.animationSpeed }, function() { windowStack[windowStackCurrent].opacity = 0; });
                windowStack[next].animate({ left:0, duration:$$.animationSpeed }, function() { windowStack[next].left = 0; windowStack[next].opacity = 1; });
                windowStackCurrent = next;
            }
            if (windowStackCurrent>0) {
                self.rightNavButton = null;
                self.leftNavButton = btnBack;
            }
        });
        Ti.App.addEventListener('app:assess.stackRetreat', function(e) {
            if (windowStackCurrent>0) {
                var prev = windowStackCurrent-1;
                windowStack[prev].animate({ opacity:1, duration:$$.animationSpeed }, function() { windowStack[prev].opacity = 1; });
                windowStack[windowStackCurrent].animate({ left:'100%', duration:$$.animationSpeed }, function() { windowStack[windowStackCurrent].left = '100%'; });
                windowStackCurrent = prev;
            }
            if (windowStackCurrent<1) {
                self.rightNavButton = btnSelectPlayer;
                self.leftNavButton = null;
            }
        });
        Ti.App.addEventListener('app:assess.stackReset', function(e) {
            windowStackCurrent = 0;
 
            for (i=windowStack.length-1; i>0; i--) {
                windowStack[i].left = '100%';
                windowStack[i].opacity = 1;
            }
 
            windowStack[0].left = 0;
            windowStack[0].opacity = 1;
 
            self.rightNavButton = btnSelectPlayer;              
        });
 
 
        //Reset the stack the first time it's loaded
        Ti.App.fireEvent('app:assess.stackReset');
 
        return self;
    };
})();

— asked 1 year ago by David Webb
1 Comment
  • Forgot to mention that everything works (advance and retreat) if I don't animate anything (just using show and hide). But, that's what makes life worth living!

    — commented 1 year ago by David Webb

1 Answer

Looks like I was doing two things incorrectly:

  1. (this is a stupid one) I wasn't properly accounting for "animate" running asynchronously (which threw my array counters all out of whack, selecting the wrong items in the stack at the wrong time). Simple fix for this one was to move the remaining variable assignments at the end of the "advance" and "retreat" functions into the callback function of animate, so that they all fire sequentially after the animation is complete.

  2. Animate doesn't seem to like relative widths (I had the views set to "100%" instead of just using point width - I already had a global variable in my "stylesheet" with the platform width).

Once I corrected those two, everything's working great!

Your Answer

Think you can help? Login to answer this question!