Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-17260] Android: Animation is broken if you don't stringify the affected view

GitHub Issuen/a
TypeBug
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2014-09-04T22:47:04.000+0000
Affected Version/sRelease 3.2.3, Release 3.3.0
Fix Version/sRelease 4.0.0
ComponentsAndroid
Labelsmodule_animation, qe-manualtest, qe-testadded
ReporterFix Please
AssigneeSunila
Created2014-05-30T20:58:20.000+0000
Updated2015-02-16T09:23:27.000+0000

Description

Problem Description

Three (red, blue, green) square views should move from top of the screen ([ 0,50], [0,80], [0,random]) to the same target position [300, 300] (grey square). They **only** move as expected after you add a stringify the view. See the video attached. I managed to recreate the issue on the GT-S7562 device as well.

Steps to reproduce

1. Create a new mobile project (classic titanium) 2. Add this code to app.js
var win = Ti.UI.createWindow({
    backgroundColor:'white',
});
 
var viewo = Ti.UI.createView({
    backgroundColor:'#888',
    top:300,
    left:300,
    width:100,
    height:100,
});
 
win.add(viewo);
 
function createView(color, id){
  return Ti.UI.createView({
    backgroundColor: color,
    width: 100,
    height: 100,
    opacity: 0.5,
    id: id
  });
}
  
var view1 = createView('green', '1');
var view2 = createView('blue', '2');
var view3 = createView('red', '3');
  
var animation1 = Ti.UI.createAnimation();
var animation2 = Ti.UI.createAnimation();
var animation3 = Ti.UI.createAnimation();
  
animation1.addEventListener('complete', function() {
  //Ti.API.info('animation1 complete. view: ' + JSON.stringify(view1));
  startAll();
});
    
animation2.addEventListener('complete', function() {
  //Ti.API.info('animation2 complete. view: ' + JSON.stringify(view2));
});
    
animation3.addEventListener('complete', function() {
  //Ti.API.info('animation3 complete. view: ' + JSON.stringify(view3));
});
  
function initAnimation(animation){
  animation.left = 300;
  animation.top = 300;
  animation.duration = 5000;  
}
  
function startAnimation(x, view, animation){
  view.setLeft(x);
  view.setTop(0);
    
  initAnimation(animation);
    
  JSON.stringify(view); // Comment out this line in order to see the bug in your emulator.
  view.animate(animation);  
}
  
function startAnimation1(){
  var startX = 50;
  startAnimation(startX, view1, animation1);  
}
  
var startX = 50;
function startAnimation2(){
  startX += 30;
  startAnimation(startX, view2, animation2);  
}
  
function startAnimation3(){
  var startX = Math.floor(Math.random() * 500);
  startAnimation(startX, view3, animation3); 
}
  
function startAll(){
  setTimeout(function(){
    startAnimation1();
    startAnimation2();
    startAnimation3();
  }, 3000);
}
  
win.add(view1);
win.add(view2);
win.add(view3);
  
win.open();
  
startAll();
3. Comment out the line with the comment "Comment out this line in order to see the bug in your emulator.". 4. Run it in emulator to see the issue (the animation breaks down when you comment out the line in step 3 - if you add it again, it will work as expected).

Extra info

Please check the video for more information.

Attachments

FileDateSize
animation3.avi2014-05-30T20:58:20.000+00003857000

Comments

  1. Mauro Parra-Miranda 2014-06-30

    Hello, can you please describe the issue? We need stuff like: - Description of the problem - Steps to reproduce (already provided) - Expected behavior - Actual behavior I add here the classic titanium sample:
       var win = Ti.UI.createWindow({
       	backgroundColor:'white',
       });
       
       var viewo = Ti.UI.createView({
       	backgroundColor:'#888',
       	top:300,
       	left:300,
       	width:100,
       	height:100,
       });
       
       win.add(viewo);
       
       function createView(color, id){
         return Ti.UI.createView({
           backgroundColor: color,
           width: 100,
           height: 100,
           opacity: 0.5,
           id: id
         });
       }
        
       var view1 = createView('green', '1');
       var view2 = createView('blue', '2');
       var view3 = createView('red', '3');
        
       var animation1 = Ti.UI.createAnimation();
       var animation2 = Ti.UI.createAnimation();
       var animation3 = Ti.UI.createAnimation();
        
       animation1.addEventListener('complete', function() {
         //Ti.API.info('animation1 complete. view: ' + JSON.stringify(view1));
         startAll();
       });
          
       animation2.addEventListener('complete', function() {
         //Ti.API.info('animation2 complete. view: ' + JSON.stringify(view2));
       });
          
       animation3.addEventListener('complete', function() {
         //Ti.API.info('animation3 complete. view: ' + JSON.stringify(view3));
       });
        
       function initAnimation(animation){
         animation.left = 300;
         animation.top = 300;
         animation.duration = 5000;  
       }
        
       function startAnimation(x, view, animation){
         view.setLeft(x);
         view.setTop(0);
          
         initAnimation(animation);
          
         JSON.stringify(view); // !!!
         view.animate(animation);  
       }
        
       function startAnimation1(){
         var startX = 50;
         startAnimation(startX, view1, animation1);  
       }
        
       var startX = 50;
       function startAnimation2(){
         startX += 30;
         startAnimation(startX, view2, animation2);  
       }
        
       function startAnimation3(){
         var startX = Math.floor(Math.random() * 500);
         startAnimation(startX, view3, animation3); 
       }
        
       function startAll(){
         setTimeout(function(){
           startAnimation1();
           startAnimation2();
           startAnimation3();
         }, 3000);
       }
        
       win.add(view1);
       win.add(view2);
       win.add(view3);
        
       win.open();
        
       startAll();
       
       
    Thanks for reporting!
  2. Fix Please 2014-07-01

    I've spent my time to record a video that is clear more than enough even with no source code. But the code is provided as well. You need a formal description? Ok, here you are: *Description of the problem:* Animation does not work as expected. "JSON.stringify(view);" string magically fix the problem if added to the code as it shown in the video and in the code attached. *Expected behavior:* 1. Animation should work properly, i.e. as it written in the code. 2. "JSON.stringify(view);" should not affect animation. *Actual behavior:* 1. Animation does not work properly. 2. "JSON.stringify(view);" affects animation. PS. Please, spend 2 minutes to watch the video attached. I've spent much more time to record it for you. Thanks.
  3. Mauro Parra-Miranda 2014-07-01

    Hello, so the ddescription: Animation is failing if you don't add JSON.stringify(view)? Like if the stringify "fixes" the issue? Just to be clear. Best Regards
  4. Fix Please 2014-07-01

    I can't believe that. Your computer can't play avi? Should I make and attach screenshots? As it clear from the video, animation is shown totally incorrect with no stringify injected.
  5. Mauro Parra-Miranda 2014-07-01

    Hello [~fixplease]. We played your video, there is no sound, there is only some signs of things that you point to. If you can provide a detailed description of your problem, we can help you. In this moment, we don't have your context or what exactly is wrong here. Please take a look into the best practices to report an issue: https://wiki.appcelerator.org/display/guides2/How+to+Submit+a+Bug+Report Best Regards
  6. Fix Please 2014-07-01

    Mauro, it's all about animation, not about sound. What sound do you need? I can sing something for you if it could help. But I have to warn I'm a bad singer. Do you understand the code attached? Is it clear what should be shown on device screen as the result of the code execution? Should I explain the code for you? I assumed that the code is self-descriptive.... Hmmmm......
  7. Mauro Parra-Miranda 2014-07-01

    Hello [~fixplease], Thanks for providing a testcase. But still, you need to provide: - Problem Description. What the problem is? By example: When I animate the view1 30 rad to the left, it does only 27. - Test case - Provide an app.js, and instructions like: 1. Create new mobile project (classic titanium). 2. Paste app.js with the provided test case. 3. Run it in a device, so you can see the issue. - Environment. This happened to me when I was using Ti Studio Version x.XX, Mobile SDK x.xx, etc. I understand your frustration over this. We are processing few hundreds TC bugs here. Any little clarity about your bug, will be really helpful to speed things up. And believe, we really thank you for taking this time and interest in reporting issues. But it needs certain level of detail in order to be useful to the Platform team (or any team involved). Best Regards
  8. Fix Please 2014-07-01

    {quote} what exactly is wrong here {quote} According to the code the 3 (red, blue, green) square views should move from top of the screen (\[ 0,50\], \[0,80\], \[0,random\]) to the same target position \[300, 300\] (grey square). They really move as expected but only in case of the stringify is injected. And they move in unpredictable way once the stringify code line is commented out. And it's clearly shown in the video.
  9. Fix Please 2014-07-01

    {quote} But it needs certain level of detail {quote} All the details are here. You just don't want to see them. I'm almost sure that fixing the bug could take less time than I've already spent with you for nothing.
  10. Mauro Parra-Miranda 2014-07-01

    Thanks for your report. The priority will be set by the platform team.
  11. Fix Please 2014-07-01

    Thanks, Mauro
  12. Sunila 2014-07-19

    I don't think Stringfy make the animation work. It just that once 'left' and 'top' of the view is set, layout needs to be triggered for the properties to be set internally otherwise the animation will use the value that was already there (which is the ending position of the animation). The same code will work, if there is delay after the 'left' and 'top' properties are set like calling view.animate(animation) in a setTimeout I think the better approach will be to set 'top', 'left' for all views and then start the animation, something like
                    var win = Ti.UI.createWindow({
        	    backgroundColor:'white',
        	});
        	  
        	var viewo = Ti.UI.createView({
        	    backgroundColor:'#888',
        	    top:300,
        	    left:300,
        	    width:100,
        	    height:100,
        	});
        	  
        	win.add(viewo);
        	  
        	function createView(color, id){
        	  return Ti.UI.createView({
        	    backgroundColor: color,
        	    width: 100,
        	    height: 100,
        	    opacity: 0.5,
        	    id: id
        	  });
        	}
        	   
        	var view1 = createView('green', '1');
        	var view2 = createView('blue', '2');
        	var view3 = createView('red', '3');
        	   
        	var animation1 = Ti.UI.createAnimation();
        	var animation2 = Ti.UI.createAnimation();
        	var animation3 = Ti.UI.createAnimation();
        	   
        	animation1.addEventListener('complete', function() {
        	  startAll();
        	});
        	   
        	function initAnimation(animation){
        	  animation.left = 300;
        	  animation.top = 300;
        	  animation.duration = 5000;  
        	}
        	   
        	function startAnimation(view, animation){
        
        	  initAnimation(animation);
        
        	  view.animate(animation);
        	}
        	   
        	function startAnimation1(){
        	  startAnimation(view1, animation1);  
        	}
        	   
        	function startAnimation2(){
        	  startAnimation(view2, animation2);  
        	}
        	   
        	function startAnimation3(){
        	  startAnimation( view3, animation3); 
        	}
        	   
        	function startAll(){
        		  view1.setLeft(50);
        		  view1.setTop(0);
        		  view2.setLeft(80);
        		  view2.setTop(0);
        		  view3.setLeft(Math.floor(Math.random() * 500));
        		  view3.setTop(0);
        		  
        	  setTimeout(function(){
        	    startAnimation1();
        	    startAnimation2();
        	    startAnimation3();
        	  }, 50);
        	}
        
        	win.add(view1);
        	win.add(view2);
        	win.add(view3);
        	   
        	win.open();
        	   
        	startAll();
        
  13. Fix Please 2014-07-23

    {quote} var i,j=0; for (i=0;i<40000000;i++) {j++;} or calling view.animate(animation) in a setTimeout {quote} Sunila, are you serious??? Should I use the proposed loop in production code? Are you serious? I don't think that my code is a kind of incorrect or 'sophisticated'. The code is easy and straightforward. I don't care about "set internally" as I have no way to control that. It's a BUG if something does not work as expected in the internals. I'm really surprised that you suggest to use such kind of dirty code instead of fixing the BUG. Sunila, please, re-open the bug and assign it to a more competent person. Thanks
  14. Ingo Muschenetz 2014-07-23

    [~fixplease] We have had multiple complaints from members of the community about inappropriate tone and language by you, both in this ticket and others. This behavior is unacceptable. As an open-source community that values transparency and respect, we appreciate constructive feedback. Anonymity does not exempt contributors from these standards. This is free software. There is no obligation to use it, and we are under no obligation to help belligerent users with it. Your input and insight is valuable, but to remain on this forum, you need to reconsider your approach.
  15. Sunila 2014-07-23

    Apologies if my comment was not clear. My intention was not to suggest the use of 'loop' to solve the issue but to say that the stringify has nothing to do with the issue and any calls that introduce a delay will also work. As you can see, in the modified sample I put there, there is no loop and I just moved the existing code that sets the 'left' and 'top' properties to outside of the 'setTimeout' and it works.
  16. Fix Please 2014-07-23

    Ingo, let's leave moral aspects and could you explain why the bug is closed as 'invalid' instead? I'm spending my time helping you to improve the product. But from the other (your) side I feel something like "don't bother us, we are busy". And this thread illustrates this well. Review it from the beginning. I've provided not only the code but even recorded video that clearly explains the issue. And how the item was processed at your side? Imho, this thread really illustrates how software shouldn't be being developed. Don't you think that "this is unacceptable"? I can't be patient in such cases as I'm spending my time for nothing. I'd like to know your opinion, TIMOB-17260 is a bug or not? That's a simple question. Could you answer, please?
  17. Fix Please 2014-07-23

    {quote} I just moved the existing code that sets the 'left' and 'top' properties to outside of the 'setTimeout' and it works. {quote} Sunila, that's great that it magically works. But, you know, I don't like voodoo techniques in software development. And even more - I hate such techniques. Could you answer, please, what is wrong in my code? The code is incorrect? What is incorrect if so? Thanks.
  18. Eric Merriman 2014-07-24

    We have a little more information here. We validated that with the existing code, it seems to work if we use the stringify or even if we console.log the views as they are passed in to the function. We were able to get more of a clue as to what is happening when we refactored the example code. We moved some items around but still had issues. It was when we include a small delay in the "startAnimation" function that things start working without the stringify. It seems to indicate that there is a timing issue. In the case of the refactored sample perhaps related to the setting of the left and top, then immediately animating. With a 100 millisecond delay before animating, things seem to work. We will continue to investigate.
        var win = Ti.UI.createWindow({backgroundColor:'white'}),
        	view0 = Ti.UI.createView({backgroundColor:'#888', top:300, left:300, width:100, height:100}),  
        	animation1 = Ti.UI.createAnimation({left:300, top:300, duration:5000}),
        	animation2 = Ti.UI.createAnimation({left:300, top:300, duration:5000}),
        	animation3 = Ti.UI.createAnimation({left:300, top:300, duration:5000}),
        	startX = 50;
        
        function createView(color, id, left){
        	return Ti.UI.createView({
        		backgroundColor: color,
        		top:0,
        		left:left,
        		width: 100,
        		height: 100,
        		opacity: 0.5,
        		id: id
        	});
        }
          
        var view1 = createView('green', '1', 50),
        	view2 = createView('blue', '2', 80),
        	view3 = createView('red', '3', Math.floor(Math.random() * 500));
        
        animation1.addEventListener('complete', function() { Ti.API.info('Animation 1 Complete'); setTimeout(function(){ startAll(); }, 3000); });
        animation2.addEventListener('complete', function() { Ti.API.info('Animation 2 Complete'); });
        animation3.addEventListener('complete', function() { Ti.API.info('Animation 3 Complete'); });
        
        function startAnimation(x, view, animation){
        	view.setLeft(x);
        	view.setTop(0);
        	setTimeout(function(){ 
        		view.animate(animation);
        	}, 100);  // this delay seems to allow expected results.
        }
        
        function startAnimation1(){
        	var startX = 50;
        	startAnimation(startX, view1, animation1);  
        }
        
        function startAnimation2(){
        	startX += 30;
        	startAnimation(startX, view2, animation2);  
        }
        
        function startAnimation3(){
        	var startX = Math.floor(Math.random() * 500);
        	startAnimation(startX, view3, animation3); 
        }
        
        function startAll(){
        	startAnimation1();
        	startAnimation2();
        	startAnimation3();
        }
        
        win.add(view0);
        win.add(view1);
        win.add(view2);
        win.add(view3);
        win.open();
        startAll();
        
  19. Fix Please 2014-07-28

    {quote} We will continue to investigate. {quote} Shouldn't the item be re-opened? Btw, *Ingo*, will you answer or not?
  20. Ingo Muschenetz 2014-07-28

    Reopening to discuss in triage. It appears from the responses this is a timing issue, so once we determine the root cause or an acceptable workaround, we should update the title/description to match.
  21. Sunila 2014-08-03

    Modified the animate code to queue up a new request if there is layout pending. https://github.com/appcelerator/titanium_mobile/pull/5946
  22. Fix Please 2014-09-01

    Hi What is the current status of the item? Seems, code review has been done a month ago.
  23. Lokesh Choudhary 2014-10-03

    Verified the fix on latest 3.5.0 SDK. Waiting for merge to 3.4.1 SDK to close. Environment: Appc Studio : 3.4.0.201409261245 Ti SDK : 3.5.0.v20141002192515 Mac OSX : 10.9.4 Alloy : 1.5.1 CLI - 3.4.0 Code Processor: 1.1.1 Nexus 5 - Android 4.4.4
  24. Khushbu Agrawal 2015-02-16

    Verified the fix on below Test Environment Appc Studio : 4.0.0.201502111039 Ti SDK : 4.0.0.v20150213151526 Mac OSX : 10.10.1 Alloy : 1.5.1 CLI - 3.6.0-dev Code Processor: 1.1.1 Nexus 5 - Android 5.0 Three (red, blue, green) square views moves from top of the screen ([ 0,50], [0,80], [0,random]) to the same target position [300, 300] (grey square) without stringify the view. So Closing this ticket.

JSON Source