Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-16087] Android: Content inside of an animating container does not behave as expected

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2014-01-22T22:21:52.000+0000
Affected Version/sRelease 3.2.0
Fix Version/s2014 Sprint 02, 2014 Sprint 02 API, Release 3.2.3, Release 3.3.0
ComponentsAndroid
Labelsandroid, module_animation, parity, qe-closed-3.2.3, qe-testadded, regression
ReporterMatthew Congrove
AssigneePing Wang
Created2013-12-26T21:23:14.000+0000
Updated2014-04-18T20:25:26.000+0000

Description

Animations that worked in 3.1.X on Android have now changed behavior and broken pre-existing UX. There are two problems I've noticed thus far: 1) Content inside of an animating container does not behave as expected 2) Animating views do not properly push aside other views inside the same container, e.g. with layout horizontal (duplicate of TIMOB-15951) Sample code, for TABLET only, is available here: https://github.com/mcongrove/TitaniumAnimationDemo After installing the application on an Android tablet, try the following steps: 1) At the top-right of the application, swipe down on the "Alert: TiDev.io Launches" black bar. This should act as a drawer to display new content, but instead the black bar view simply stretches. 2) On the first large content box (grey), tap the full-screen button in the top-right. Instead of pushing the following boxes, it instead expands behind them. It also stretches all content inside the box. To see how any of this SHOULD work, run the application on an iPad.

Comments

  1. Ingo Muschenetz 2013-12-26

    Matt, is issue #2 TIMOB-15951?
  2. Matthew Congrove 2013-12-26

    Ingo, yes, it looks to be the same as the second issue I've reported. Sorry, I didn't see that one in my search :)
  3. Ingo Muschenetz 2013-12-26

    No problem. I'm glad, as otherwise I was going to ask you to file two separate tickets. :) I'll repurpose this one for issue #1.
  4. Ping Wang 2014-01-02

    Test case:
       var win = Ti.UI.createWindow({
           backgroundColor: "white"
       });
        
       var bBig = false;
         
       var btn1 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Scaling Test - vertical layout',
           top: 0
       } );
        
       var btn1_2 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Translation Test - vertical layout',
           top: '40dp'
       } );
         
       var parent1 = Ti.UI.createView({
           top: '250dp',
           left: 0,
           height: 100,
           width: 100,
           backgroundColor: 'yellow',
           layout: 'vertical'
       });
         
       var v1 = Ti.UI.createView({
           height: 30,
           width: 50,
           top: 5,
           backgroundColor: 'red'
       });
        
       var v1_1 = Ti.UI.createView({
           //height: '50%',
           //width: '50%',
           height: 15,
           width: 25,
           backgroundColor: 'green'
       });
       v1.add(v1_1);
         
       var v2 = Ti.UI.createView({
           height: 50,
           width: 50,
           top: 20,
           backgroundColor: 'blue'
       });
         
       btn1.addEventListener( 'click', function( e ) {
           if( !bBig ){
               bBig = true;
               var animation1 = Ti.UI.createAnimation({
                   height:70,
                   width: 80,
                   duration: 300
               });
               v1.animate(animation1);
           } else {
               bBig = false;
               var animation1 = Ti.UI.createAnimation({
                   height:30,
                   width: 50,
                   duration: 300
               });
               v1.animate(animation1);
           }
       } );
        
       var bBig_2 = false;
       btn1_2.addEventListener( 'click', function( e ) {
           if( !bBig_2 ){
               bBig_2 = true;
               var animation1 = Ti.UI.createAnimation({
                   top: 40,
                   duration: 300
               });
               v1.animate(animation1);
           } else {
               bBig_2 = false;
               var animation1 = Ti.UI.createAnimation({
                   top: 5,
                   duration: 300
               });
               v1.animate(animation1);
           }
       } );
        
        
       win.add( btn1 );
       win.add( btn1_2 );
       win.add( parent1 );
          
       parent1.add( v1 );
       parent1.add( v2 );
        
       //******************************************************
       var bBig1 = false;
        
       var btn2 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Scaling Test - horizontal layout',
           top: '80dp',
       } );
        
       var btn2_2 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Translation Test - horizontal layout',
           top: '120dp',
       } );
         
       var parent2 = Ti.UI.createView({
           top: '250dp',
           left: 105,
           height: 100,
           width: 120,
           backgroundColor: 'yellow',
           layout: 'horizontal'
       });
         
       var v3 = Ti.UI.createView({
           height: 50,
           width: 30,
           left: 5,
           backgroundColor: 'red'
       });
        
       var v3_1 = Ti.UI.createView({
           // height: '50%',
           // width: '50%',
           height: 25,
           width: 15,
           backgroundColor: 'green'
       });
       v3.add(v3_1);
         
       var v4 = Ti.UI.createView({
           height: 50,
           width: 50,
           left: 20,
           backgroundColor: 'blue'
       });
         
       btn2.addEventListener( 'click', function( e ) {
           if( !bBig1 ){
               bBig1 = true;
               var animation3 = Ti.UI.createAnimation({
                   width:70,
                   height: 70,
                   duration: 300
               });
               v3.animate(animation3);
           } else {
               bBig1 = false;
               var animation3 = Ti.UI.createAnimation({
                   width:30,
                   height: 50,
                   duration: 300
               });
               v3.animate(animation3);
           }
       } );
        
       var bBig1_2 = false;
       btn2_2.addEventListener( 'click', function( e ) {
           if( !bBig1_2 ){
               bBig1_2 = true;
               var animation3 = Ti.UI.createAnimation({
                   left: 40,
                   duration: 300
               });
               v3.animate(animation3);
           } else {
               bBig1_2 = false;
               var animation3 = Ti.UI.createAnimation({
                   left: 5,
                   duration: 300
               });
               v3.animate(animation3);
           }
       } );
        
       win.add( btn2 );
       win.add( btn2_2 );
       win.add( parent2 );
         
       parent2.add( v3 );
       parent2.add( v4 );
        
       //******************************************************
       var bBig2 = false;
        
       var btn3 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Scaling Test - composite layout',
           top: '160dp',
       } );
        
       var btn3_2 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Translation Test - composite layout',
           top: '200dp',
       } );
         
       var parent3 = Ti.UI.createView({
           top: '250dp',
           left: 230,
           height: 100,
           width: 120,
           backgroundColor: 'yellow'
       });
         
       var v5 = Ti.UI.createView({
           height: 50,
           width: 50,
           left: 5,
           backgroundColor: 'red'
       });
        
       var v5_1 = Ti.UI.createView({
           //height: '50%',
           //width: '50%',
           height: '25',
           width: '25',
           backgroundColor: 'green'
       });
       v5.add(v5_1);
         
       var v6 = Ti.UI.createView({
           height: 50,
           width: 50,
           left: 60,
           backgroundColor: 'blue'
       });
         
       btn3.addEventListener( 'click', function( e ) {
           if( !bBig2 ){
               bBig2 = true;
               var animation5 = Ti.UI.createAnimation({
                   width: 80,
                   height: 80,
                   duration: 300
               });
               v5.animate(animation5);
           } else {
               bBig2 = false;
               var animation5 = Ti.UI.createAnimation({
                   width: 50,
                   height: 50,
                   duration: 300
               });
               v5.animate(animation5);
           }
       } );
        
       var bBig2_2 = false;
       btn3_2.addEventListener( 'click', function( e ) {
           if( !bBig2_2 ){
               bBig2_2 = true;
               var animation5 = Ti.UI.createAnimation({
                   left: 50,
                   duration: 300
               });
               v5.animate(animation5);
           } else {
               bBig2_2 = false;
               var animation5 = Ti.UI.createAnimation({
                   left: 5,
                   duration: 300
               });
               v5.animate(animation5);
           }
       } );
        
       win.add( btn3 );
       win.add( btn3_2 );
       win.add( parent3 );
        
       parent3.add( v5 );
       parent3.add( v6 );
         
       win.open();
       
    In 3.2.0.GA, click "Scaling Test". The green view is scaled up/down along with the red view. In 3.1.3.GA, click "Scaling Test". The green view keeps the same size while the red view is scaled up/down.
  5. Ping Wang 2014-01-02

    The root issue is the children views are scaled up/down with the parent view even the dimensions of the children views are defined as absolute values (eg. "50px"). This is not our bug but a native Android behavior when using Honeycomb+ Property Animation which is introduced in 3.2.0. However, technically speaking, this is a regression.
  6. Ping Wang 2014-01-03

    If the developer wants to keep the size of the child view unchanged while the parent view is scaled, one workaround is to scale the child view to compensate the size change. For the above test case, we can use the workaround like:
       var win = Ti.UI.createWindow({
           backgroundColor: "white"
       });
          
       var bBig = false;
           
       var btn1 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Scaling Test - vertical layout',
           top: 0
       } );
          
       var btn1_2 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Translation Test - vertical layout',
           top: '40dp'
       } );
           
       var parent1 = Ti.UI.createView({
           top: '250dp',
           left: 0,
           height: 100,
           width: 100,
           backgroundColor: 'yellow',
           layout: 'vertical'
       });
           
       var v1 = Ti.UI.createView({
           height: 30,
           width: 50,
           top: 5,
           backgroundColor: 'red'
       });
          
       var v1_1 = Ti.UI.createView({
           height: 15,
           width: 25,
           backgroundColor: 'green'
       });
       v1.add(v1_1);
           
       var v2 = Ti.UI.createView({
           height: 50,
           width: 50,
           top: 20,
           backgroundColor: 'blue'
       });
           
       btn1.addEventListener( 'click', function( e ) {
           if( !bBig ){
               bBig = true;
               var animation1 = Ti.UI.createAnimation({
                   height:70,
                   width: 80,
                   duration: 300
               });
               v1.animate(animation1);
               
               // For Android API level >= 11, we need to animate the child
               // view to keep the child size unchanged.
       		if (Ti.Platform.Android.API_LEVEL >= 11) {
       			var animation1_1 = Ti.UI.createAnimation({
       				height : 15 * 30.0 / 70.0,
       				width : 25 * 50.0 / 80.0,
       				duration : 300
       			});
       			v1_1.animate(animation1_1);
       		}
       
           } else {
               bBig = false;
               var animation1 = Ti.UI.createAnimation({
                   height:30,
                   width: 50,
                   duration: 300
               });
               v1.animate(animation1);
               
       		if (Ti.Platform.Android.API_LEVEL >= 11) {
       			var animation1_1 = Ti.UI.createAnimation({
       				height : 15,
       				width : 25,
       				duration : 300
       			});
       			v1_1.animate(animation1_1);
       		}
       
           }
       } );
          
       var bBig_2 = false;
       btn1_2.addEventListener( 'click', function( e ) {
           if( !bBig_2 ){
               bBig_2 = true;
               var animation1 = Ti.UI.createAnimation({
                   top: 40,
                   duration: 300
               });
               v1.animate(animation1);
           } else {
               bBig_2 = false;
               var animation1 = Ti.UI.createAnimation({
                   top: 5,
                   duration: 300
               });
               v1.animate(animation1);
           }
       } );
          
          
       win.add( btn1 );
       win.add( btn1_2 );
       win.add( parent1 );
            
       parent1.add( v1 );
       parent1.add( v2 );
          
       //******************************************************
       var bBig1 = false;
          
       var btn2 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Scaling Test - horizontal layout',
           top: '80dp',
       } );
          
       var btn2_2 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Translation Test - horizontal layout',
           top: '120dp',
       } );
           
       var parent2 = Ti.UI.createView({
           top: '250dp',
           left: 105,
           height: 100,
           width: 120,
           backgroundColor: 'yellow',
           layout: 'horizontal'
       });
           
       var v3 = Ti.UI.createView({
           height: 50,
           width: 30,
           left: 5,
           backgroundColor: 'red'
       });
          
       var v3_1 = Ti.UI.createView({
           height: 25,
           width: 15,
           backgroundColor: 'green'
       });
       v3.add(v3_1);
           
       var v4 = Ti.UI.createView({
           height: 50,
           width: 50,
           left: 20,
           backgroundColor: 'blue'
       });
           
       btn2.addEventListener( 'click', function( e ) {
           if( !bBig1 ){
               bBig1 = true;
               var animation3 = Ti.UI.createAnimation({
                   width:70,
                   height: 70,
                   duration: 300
               });
               v3.animate(animation3);
               
               // For Android API level >= 11, we need to animate the child
               // view to keep the child size unchanged.
       		if (Ti.Platform.Android.API_LEVEL >= 11) {
       			var animation3_1 = Ti.UI.createAnimation({
       				height : 25 * 50.0 / 70.0,
       				width : 15 * 30.0 / 70.0,
       				duration : 300
       			});
       			v3_1.animate(animation3_1);
       		}
       
           } else {
               bBig1 = false;
               var animation3 = Ti.UI.createAnimation({
                   width:30,
                   height: 50,
                   duration: 300
               });
               v3.animate(animation3);
               
       		if (Ti.Platform.Android.API_LEVEL >= 11) {
       			var animation3_1 = Ti.UI.createAnimation({
       				height : 25,
       				width : 15,
       				duration : 300
       			});
       			v3_1.animate(animation3_1);
       		}
       
           }
       } );
          
       var bBig1_2 = false;
       btn2_2.addEventListener( 'click', function( e ) {
           if( !bBig1_2 ){
               bBig1_2 = true;
               var animation3 = Ti.UI.createAnimation({
                   left: 40,
                   duration: 300
               });
               v3.animate(animation3);
           } else {
               bBig1_2 = false;
               var animation3 = Ti.UI.createAnimation({
                   left: 5,
                   duration: 300
               });
               v3.animate(animation3);
           }
       } );
          
       win.add( btn2 );
       win.add( btn2_2 );
       win.add( parent2 );
           
       parent2.add( v3 );
       parent2.add( v4 );
          
       //******************************************************
       var bBig2 = false;
          
       var btn3 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Scaling Test - composite layout',
           top: '160dp',
       } );
          
       var btn3_2 = Ti.UI.createButton( {
           width : '90%',
           height : '40dp',
           title : 'Translation Test - composite layout',
           top: '200dp',
       } );
           
       var parent3 = Ti.UI.createView({
           top: '250dp',
           left: 230,
           height: 100,
           width: 120,
           backgroundColor: 'yellow'
       });
           
       var v5 = Ti.UI.createView({
           height: 50,
           width: 50,
           left: 5,
           backgroundColor: 'red'
       });
          
       var v5_1 = Ti.UI.createView({
           height: '25',
           width: '25',
           backgroundColor: 'green'
       });
       v5.add(v5_1);
           
       var v6 = Ti.UI.createView({
           height: 50,
           width: 50,
           left: 60,
           backgroundColor: 'blue'
       });
           
       btn3.addEventListener( 'click', function( e ) {
           if( !bBig2 ){
               bBig2 = true;
               var animation5 = Ti.UI.createAnimation({
                   width: 80,
                   height: 80,
                   duration: 300
               });
               v5.animate(animation5);
               
               // For Android API level >= 11, we need to animate the child
               // view to keep the child size unchanged.
       		if (Ti.Platform.Android.API_LEVEL >= 11) {
       			var animation5_1 = Ti.UI.createAnimation({
       				height : 25 * 50.0 / 80.0,
       				width : 25 * 50.0 / 80.0,
       				duration : 300
       			});
       			v5_1.animate(animation5_1);
       		}
       
           } else {
               bBig2 = false;
               var animation5 = Ti.UI.createAnimation({
                   width: 50,
                   height: 50,
                   duration: 300
               });
               v5.animate(animation5);
               
       		if (Ti.Platform.Android.API_LEVEL >= 11) {
       			var animation5_1 = Ti.UI.createAnimation({
       				height : 25,
       				width : 25,
       				duration : 300
       			});
       			v5_1.animate(animation5_1);
       		}
       
           }
       } );
          
       var bBig2_2 = false;
       btn3_2.addEventListener( 'click', function( e ) {
           if( !bBig2_2 ){
               bBig2_2 = true;
               var animation5 = Ti.UI.createAnimation({
                   left: 50,
                   duration: 300
               });
               v5.animate(animation5);
           } else {
               bBig2_2 = false;
               var animation5 = Ti.UI.createAnimation({
                   left: 5,
                   duration: 300
               });
               v5.animate(animation5);
           }
       } );
          
       win.add( btn3 );
       win.add( btn3_2 );
       win.add( parent3 );
          
       parent3.add( v5 );
       parent3.add( v6 );
           
       win.open();
       
  7. Priya Agarwal 2014-01-07

    Using the above TestCode: Appc-Studio: 3.2.1.201401061716 acs:1.0.11 alloy:1.3.1-beta npm:1.3.2 titanium:3.2.0 titanium-code-processor:1.1.0 Osx: Maverick 10.9 Device:Nexus7(v4.4.2) Issue still exists in both sdk build:3.2.1.v20140106195644 and 3.3.0.v20140106195650 Observed Result: In 3.1.3.GA, click "Scaling Test". The green view keeps the same size while the red view is scaled up/down. In 3.2.0.GA,3.2.1.v20140106195644 and 3.3.0.v20140106195650 click "Scaling Test". The green view is scaled up/down along with the red view.
  8. Ping Wang 2014-01-16

    PR: https://github.com/appcelerator/titanium_mobile/pull/5226 For FR, please follow the testing steps in TIMOB-15951, TIMOB-16087, TIMOB-15719, TIMOB-2373, TIMOB-13536.
  9. Ping Wang 2014-01-23

    3_2_X PR: https://github.com/appcelerator/titanium_mobile/pull/5245
  10. Olga Romero 2014-03-20

    Tested and verified the correct behavior of the red and the green views. Mac osx 10.9.2 Mavericks Titanium SDK, build: 3.2.3.v20140320130134 Node.JS Version: v0.10.13 NPM Version: 1.3.2 ├── acs@1.0.14 ├── alloy@1.3.1 ├── npm@1.3.2 ├── titanium@3.2.1 └── titanium-code-processor@1.1.0 Device: Nexus 4 Android version 4.2

JSON Source