Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-19580] Customize Activity Transitions

GitHub Issuen/a
TypeTechnical task
PriorityMedium
StatusClosed
ResolutionFixed
Resolution Date2015-11-03T07:09:36.000+0000
Affected Version/sn/a
Fix Version/sRelease 5.2.0
ComponentsAndroid
Labelsnotable
ReporterChee Kiat Ng
AssigneeSrikanth Sombhatla
Created2015-09-25T03:11:29.000+0000
Updated2016-03-03T12:44:22.000+0000

Description

Activity transitions in material design apps provide visual connections between different states through motion and transformations between common elements. You can specify custom animations for enter and exit transitions and for transitions of shared elements between activities. Can be divided into transition types 1. Content transition: Activity enter and exit transition. 2. Shared element transition: Transition between elements in different activities to give a seamless experience. Mostly used for master-detail.

Comments

  1. Srikanth Sombhatla 2015-10-29

    PR: https://github.com/appcelerator/titanium_mobile/pull/7371 Use the following app.js code to test. This is an extension to tableviews example code with activity transitions added. Requires Android 5.0 and above.
       Ti.UI.setBackgroundColor('#000');
       var win = Ti.UI.createWindow({
         backgroundColor: 'black',
         exitOnClose: true,
         fullscreen: false,
         title: 'Master',
       /*  activityExitTransition: Titanium.UI.Android.TRANSITION_EXPLODE,
         activityReenterTransition: Titanium.UI.Android.TRANSITION_EXPLODE,*/
       });
       
       // generate random number, used to make each row appear distinct for this example
       function randomInt(max){
         return Math.floor(Math.random() * max) + 1;
       }
       
       var IMG_BASE = 'https://github.com/appcelerator/titanium_mobile/raw/master/demos/KitchenSink/Resources/images/';
       var defaultFontSize = Ti.Platform.name === 'android' ? 16 : 14;
       
       var tableData = [];
       
       for (var i=1; i<=20; i++){
         var row = Ti.UI.createTableViewRow({
           className:'forumEvent', // used to improve table performance
           selectedBackgroundColor:'white',
           rowIndex:i, // custom property, useful for determining the row during events
           height:110
         });
       
          var avatar = createAvatar();
          avatar.transitionName = "avatar";
          row.add(avatar);
          
         var labelUserName = Ti.UI.createLabel({
           color:'#576996',
           font:{fontFamily:'Arial', fontSize:defaultFontSize+6, fontWeight:'bold'},
           text:'Fred Smith ' + i,
           left:70, top: 6,
           width:200, height: 30,
         });
         row.add(labelUserName);
       
         var labelDetails = Ti.UI.createLabel({
           color:'#222',
           font:{fontFamily:'Arial', fontSize:defaultFontSize+2, fontWeight:'normal'},
           text:'Replied to post with id ' + randomInt(1000) + '.',
           left:70, top:44,
           width:360
         });
         row.add(labelDetails);
       
         var imageCalendar = Ti.UI.createImageView({
           image:IMG_BASE + 'custom_tableview/eventsButton.png',
           left:70, bottom: 2,
           width:32, height: 32
         });
         row.add(imageCalendar);
       
         var labelDate = Ti.UI.createLabel({
           color:'#999',
           font:{fontFamily:'Arial', fontSize:defaultFontSize, fontWeight:'normal'},
           text:'on ' + randomInt(30) + ' Nov 2012',
           left:105, bottom:10,
           width:200, height:20
         });
         row.add(labelDate);
       
         tableData.push(row);
       }
       
       var tableView = Ti.UI.createTableView({
         backgroundColor:'white',
         data:tableData
       });
       
       tableView.addEventListener('click', function(e){
       	var masterAvatar = e.row.children[0];
       	var masterUsername = e.row.children[1];
       	
       	var win2 = Ti.UI.createWindow({
       	  layout: 'vertical',
       	  backgroundColor: 'white',
       	  title: 'Details',
       	});
       	
       	var avatar = createAvatar();
       	avatar.width = 80;
       	avatar.height = 80;
       	avatar.left = 100;
       	avatar.transitionName = "avatar";
         	var labelUserName2 = Ti.UI.createLabel({
       	    color:'#576996',
       	    font:{fontFamily:'Arial', fontSize:defaultFontSize+6, fontWeight:'bold'},
       	    text:'Fred Smith',
       	    top: 20,
       	    width:250, height: 60,
       	    transitionName: "username",
       	  });
       	  
       	win2.add(avatar)  
           win2.add(labelUserName2);
       	win2.addSharedElement(masterAvatar, "avatar");
       	win2.addSharedElement(masterUsername, "username"); 
       	win2.open();
       });
       win.add(tableView);
       win.open();
       
       function createAvatar() {
         var avatar = Ti.UI.createView({
           backgroundColor: 'green',
           left:10, top:5,
           width:50, height:50,
         });
         return avatar; 
       }
       
  2. Ashraf Abu 2015-10-30

    PR Merged. Please note that on Android 5.0 onwards with this fix, opening a window will default to a cross-fading transition to move forward to support more Material capabilities. See: http://developer.android.com/training/material/animations.html#Transitions {quote} the default cross-fading transition is activated between the entering and exiting activities. {quote}
  3. Ashraf Abu 2015-11-03

    [~ssombhatla] Having errors running this code:-
       var win = Ti.UI.createWindow({
       	backgroundColor: 'white'
       });
        
       function createCard(layout, wrap) {
        
       	var card = Ti.UI.Android.createCardView({
       		top: 20,
       		width: Ti.UI.FILL,
       		height: 160,
        
       		layout: layout
       	});
        
       	var view;
        
       	if (wrap) {
        
       		view = Ti.UI.createView({
       			layout: layout
       		});
        
       		card.add(view);
        
       	} else {
       		view = card;
       	}
        
       	view.add(Ti.UI.createLabel({
       		width: 50,
       		height: 100,
       		backgroundColor: 'green',
       		text: (wrap ? 'reference' : layout) + ' in green'
       	}));
        
       	view.add(Ti.UI.createLabel({
       		top: 10,
       		width: 100,
       		height: 50,
       		backgroundColor: 'red',
       		text: (wrap ? 'reference' : layout) + ' in red'
       	}));
        
       	return card;
       }
        
       var scrollView = Ti.UI.createScrollView({
       	layout: 'vertical'
       });
        
       scrollView.add(createCard('vertical', true));
       scrollView.add(createCard('composite'));
       scrollView.add(createCard('vertical'));
       scrollView.add(createCard('horizontal'));
        
       win.add(scrollView);
       win.open();
       
       11-02 23:41:10.172: E/TiApplication(23507): (main) [90,90] Sending event: exception on thread: main msg:java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewRootImpl.setPausedForTransition(boolean)' on a null object reference; Titanium 1.0,N/A,N/A
       11-02 23:41:10.172: E/TiApplication(23507): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewRootImpl.setPausedForTransition(boolean)' on a null object reference
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ActivityTransitionCoordinator.startInputWhenTransitionsComplete(ActivityTransitionCoordinator.java:897)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ActivityTransitionCoordinator.viewsTransitionComplete(ActivityTransitionCoordinator.java:885)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ExitTransitionCoordinator.getExitTransition(ExitTransitionCoordinator.java:318)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ExitTransitionCoordinator.beginTransitions(ExitTransitionCoordinator.java:365)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ExitTransitionCoordinator.-wrap0(ExitTransitionCoordinator.java)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ExitTransitionCoordinator$4.run(ExitTransitionCoordinator.java:216)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ActivityTransitionCoordinator.startTransition(ActivityTransitionCoordinator.java:773)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ExitTransitionCoordinator.startExit(ExitTransitionCoordinator.java:213)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ActivityTransitionState.startExitOutTransition(ActivityTransitionState.java:317)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.Activity.cancelInputsAndStartExitTransition(Activity.java:3960)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.Activity.startActivityForResult(Activity.java:3936)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.Activity.startActivity(Activity.java:4196)
       11-02 23:41:10.172: E/TiApplication(23507): 	at ti.modules.titanium.ui.WindowProxy.handleOpen(WindowProxy.java:161)
       11-02 23:41:10.172: E/TiApplication(23507): 	at org.appcelerator.titanium.proxy.TiWindowProxy.handleMessage(TiWindowProxy.java:101)
       11-02 23:41:10.172: E/TiApplication(23507): 	at ti.modules.titanium.ui.WindowProxy.handleMessage(WindowProxy.java:444)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.os.Handler.dispatchMessage(Handler.java:98)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.os.Looper.loop(Looper.java:148)
       11-02 23:41:10.172: E/TiApplication(23507): 	at android.app.ActivityThread.main(ActivityThread.java:5417)
       11-02 23:41:10.172: E/TiApplication(23507): 	at java.lang.reflect.Method.invoke(Native Method)
       11-02 23:41:10.172: E/TiApplication(23507): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
       11-02 23:41:10.172: E/TiApplication(23507): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
       11-02 23:41:10.197: E/AndroidRuntime(23507): FATAL EXCEPTION: main
       11-02 23:41:10.197: E/AndroidRuntime(23507): Process: com.titanium.test, PID: 23507
       11-02 23:41:10.197: E/AndroidRuntime(23507): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewRootImpl.setPausedForTransition(boolean)' on a null object reference
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ActivityTransitionCoordinator.startInputWhenTransitionsComplete(ActivityTransitionCoordinator.java:897)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ActivityTransitionCoordinator.viewsTransitionComplete(ActivityTransitionCoordinator.java:885)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ExitTransitionCoordinator.getExitTransition(ExitTransitionCoordinator.java:318)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ExitTransitionCoordinator.beginTransitions(ExitTransitionCoordinator.java:365)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ExitTransitionCoordinator.-wrap0(ExitTransitionCoordinator.java)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ExitTransitionCoordinator$4.run(ExitTransitionCoordinator.java:216)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ActivityTransitionCoordinator.startTransition(ActivityTransitionCoordinator.java:773)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ExitTransitionCoordinator.startExit(ExitTransitionCoordinator.java:213)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ActivityTransitionState.startExitOutTransition(ActivityTransitionState.java:317)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.Activity.cancelInputsAndStartExitTransition(Activity.java:3960)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.Activity.startActivityForResult(Activity.java:3936)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.Activity.startActivity(Activity.java:4196)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at ti.modules.titanium.ui.WindowProxy.handleOpen(WindowProxy.java:161)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at org.appcelerator.titanium.proxy.TiWindowProxy.handleMessage(TiWindowProxy.java:101)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at ti.modules.titanium.ui.WindowProxy.handleMessage(WindowProxy.java:444)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.os.Handler.dispatchMessage(Handler.java:98)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.os.Looper.loop(Looper.java:148)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at android.app.ActivityThread.main(ActivityThread.java:5417)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at java.lang.reflect.Method.invoke(Native Method)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
       11-02 23:41:10.197: E/AndroidRuntime(23507): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
       
  4. Srikanth Sombhatla 2015-11-03

    Issue is with using empty shared element pairs which is causing problem in Android 6.0 whereas working in Android 5.0. Applied fixed common for both versions. PR https://github.com/appcelerator/titanium_mobile/pull/7382 Use the above mentioned code for testing.
  5. Ashraf Abu 2015-11-03

    PR Merged. Please note that on Android 5.0 onwards with this fix, opening a window will default to a cross-fading transition to move forward to support more Material capabilities when you use addSharedElement. Otherwise, it uses the normal transition. See: http://developer.android.com/training/material/animations.html#Transitions {quote} the default cross-fading transition is activated between the entering and exiting activities. {quote}
  6. Ashraf Abu 2015-11-16

    PR https://github.com/appcelerator/titanium_mobile/pull/7445 merged for Doc update.
  7. Lokesh Choudhary 2016-02-02

    Verified the implementation of custom activity transitions & they work as expected. Closing. Environment: Appc Studio : 4.5.0.201601262138 Ti SDK : 5.2.0.v20160202005354 Ti CLI : 5.0.6 Alloy : 1.7.33 MAC Yosemite : 10.10.5 Appc NPM : 4.2.3-1 Appc CLI : 5.2.0-239 Node: 4.2.2 Nexus 6P - Android 6.0

JSON Source