Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Removed outdated references to releases

Table of Contents
maxLevel4
minLevel3
classtutTOC
excludeGoal.*|Resources.*|Steps.*

Objective

In this section, you will learn how you can handle device orientation. We'll take a look at your options for setting the UI orientation. Then, we'll show you how you can react to orientation changes within your app.

...

You specify the orientations your app can support by modifying the tiapp.xml file. This type of configuration controls the splash screen orientation possibilities. And it constrains which orientations the windows of your apps could possible show in, but not necessarily the orientation of a specific window.

...

By default, Titanium sets iPhone applications to support upright portrait only and iPad application to support all orientation modes.

Code Block
titletiapp.xml
linenumberstrue
languagehtml/xml
<?xml version="1.0" encoding="UTF-8"?>
<ti:app xmlns:ti="http://ti.appcelerator.org">
    <ios>
        <plist>
            <dict>
                <key>UISupportedInterfaceOrientations~iphone</key>
                <array>
                    <string>UIInterfaceOrientationPortrait</string>
                </array>
                <key>UISupportedInterfaceOrientations~ipad</key>
                <array>
                    <string>UIInterfaceOrientationPortrait</string>
                    <string>UIInterfaceOrientationPortraitUpsideDown</string>
                    <string>UIInterfaceOrientationLandscapeLeft</string>
                    <string>UIInterfaceOrientationLandscapeRight</string>
                </array>
            </dict>
        </plist>
    </ios>
</ti:app>

...

  1. Build your app in Titanium.
  2. Open the tiapp.xml file and display its XML contents.
  3. Next, you need to adjust the <android> node:
    1. From the line that reads <android xmlns:android="http://schemas.android.com/apk/res/android"/>, delete the "/" at the end (to change it from an empty tag to an opening tag).
    2. Add a new closing </android> tag
    3. Between those tags, add new <manifest></manifest> tags.
  4. Open <PROJECT_NAME>/build/android/AndroidManifest.xml in Studio (or a text editor of your choice).
  5. Copy the <application> node, which contains all of the <activity> nodes from that file, for example: 

    Code Block
    titleAndroidManifest.xml
    languagehtml/xml
    <?xml version="1.0" encoding="UTF-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.myapp.app" android:versionCode="1" android:versionName="1.0">
    	<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19"/>
     
        <!-- Start Copying Here -->
     
    	<application android:icon="@drawabe/appicon" android:label="MyApp" android:name="MyappApplication" android:debuggable="false" android:theme="@style/Theme.AppCompat">
    		<activity android:name=".MyappActivity" android:label"@string/app_name" android:theme="@style/Theme.Titanium" android:configChanges="keyboardHidden|orientation|screenSize">
    			<intent-filter>
    				<action android:name="android.intent.action.MAIN"/>
    				<category android:name="android.intent.category.LAUNCHER"/>
    			</intent-filter>
    		</activity>
    		<activity android:name="org.appcelerator.titanium.TiActivity" android:configChanges="keyboardHidden|orientation|screenSize"/>
    		<activity android:name="org.appcelerator.tianium.TiTranslucentActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:theme="@style/Theme.AppCompat.Translucent"/>
    		<activity android:name="ti.modules.titanium.ui.android.TiPreferencesActivity" android:configChanges="screenSize"/>
    	</application>
     
        <!-- Stop Copying Here -->
    
    	<uses-permission android:name="android.permission.INTERNET"/>
    	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    	<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
    </manifest>
  6. Paste them between the <manifest></manifest> tags you added to the tiapp.xml file. From now on, each time your app is built, Titanium will copy these activity tags to the Android Manifest file it generates. You're now ready to specify the UI orientation.
  7. For each activity tag, add the android:screenOrientation attribute.  Set it to the orientation type you want to use.  For example, nosensor locks the application in the device's preferred orientation mode, which is usually portrait for phones and landscape for tablets.  For a full list of orientation types, see http://developer.android.com/guide/topics/manifest/activity-element.html#screen.

The final manifest section of your tiapp.xml file should look similar to the example below. If you need to debug the application, set the application element's android:debuggable attribute to true.

Code Block
titletiapp.xml
linenumberstrue
languagexml
langxml
<?xml version="1.0" encoding="UTF-8"?>
<ti:app xmlns:ti="http://ti.appcelerator.org">
    <android xmlns:android="http://schemas.android.com/apk/res/android"/>
    	<manifest>
			<application android:icon="@drawable/appicon"
                         android:label="MyApp"
                         android:name="MyappApplication"
                         android:debuggable="false"
                         android:theme="@style/Theme.AppCompat">
				<activity android:screenOrientation="nosensor"
                          android:name=".MyappActivity"
                          android:label="@string/app_name"
                          android:theme="@style/Theme.Titanium"
                          android:configChanges="keyboardHidden|orientation|screenSize">
					<intent-filter>
						<action android:name="android.intent.action.MAIN"/>
						<category android:name="android.intent.category.LAUNCHER"/>
					</intent-filter>
				</activity>
				<activity android:screenOrientation="nosensor"
                          android:name="org.appcelerator.titanium.TiActivity"
                          android:configChanges="keyboardHidden|orientation|screenSize"/>
				<activity android:screenOrientation="nosensor"
                          android:name="org.appcelerator.titanium.TiTranslucentActivity"
                          android:configChanges="keyboardHidden|orientation|screenSize"
                          android:theme="@style/Theme.AppCompat.Translucent"/>
				<activity android:screenOrientation="nosensor"
                          android:name="ti.modules.titanium.ui.android.TiPreferencesActivity"
                          android:configChanges="screenSize"/>
			</application>  
		</manifest>
	</android>
</ti:app>

...

Note
titleiOS Platform Notes

Using the Window's orientationModes property to force the orientation of non-modal windows is considered a bad practice and will not be supported, including forcing the orientation of windows inside a NavigationWindow or TabGroup.

Modal windows should not support orientation modes that the window they are opened over do not support. Doing otherwise may cause bad visual/redraw behavior after the modal is dismissed, due to how iOS manages modal transitions. Beginning with 3.1.3, if If the orientationModes property of a modal window is undefined, then the orientations supported by this window would be the orientation modes specified in the tiapp.xml.

Code Block
linenumberstrue
languagejs
langjavascript
var win = Ti.UI.createWindow({
	/* on Android, it needs to be a "heavyweight" window */
	fullscreen: false,
	/* This works on iOS */
	orientationModes: [
		Ti.UI.PORTRAIT,
		Ti.UI.UPSIDE_PORTRAIT
	]
});
// but for Android using Titanium prior to 2.1 you have to set it after creation
win.orientationModes = [Ti.UI.PORTRAIT, Ti.UI.UPSIDE_PORTRAIT]

...

  • You want to limit to only portrait or to only landscape – set the desired orientation value in the tiapp.xml as described in the "Limiting orientation modes supported by your app" section above. You don't need to set win.orientationModes.
  • You want to have some windows (or tabs) in one orientation and other windows in another orientation – enable each of the supported orientations in tiapp.xml, then specify each window 's orientation using the win.orientationModes property.

...

The most powerful way to handle orientation is for your app to react to changes and update its UI. You'd reposition buttons, images, and so forth when the user turns their device. You detect orientation changes via the Ti.Gesture object.

Code Block
linenumberstrue
languagejs
langjavascript
Ti.Gesture.addEventListener('orientationchange',function(e) {
	// get current device orientation from
	// Titanium.Gesture.orientation

	// get orientation from event object
	// from e.orientation

	// Ti.Gesture.orientation should match e.orientation
	// but iOS and Android will report different values

	// two helper methods return a Boolean
	// e.source.isPortrait()
	// e.source.isLandscape()
});

...

Following his technique, in the orientationchange event handler, you'd fire an app-level event using Ti.App.fireEvent(). Within each of your UI components, you would have an app-level listener for that event which would update the component with new layout specifics.

Code Block
linenumberstrue
languagejs
langjavascript
Ti.Gesture.addEventListener('orientationchange',function(e) {
	Ti.App.fireEvent('orient', {portrait:e.source.isPortrait()});
});
// ... elsewhere ...
var myCustomView = function() {
	var view = Ti.UI.createView({
		top:10,
		left:10,
		/* etc */
	});
	Ti.App.addEventListener('orient', function(evt) {
		if(evt.portrait===true) {
			view.left = 10;
		} else {
			view.left = 50;
		}
	});
}

...

Splash screens are shown when your app launches. A default PNG file is provided with a new Titanium project to bue be used as your app's splash screen. You can change, but not remove entirely the splash screen: it is displayed while your app is launching and is removed when the entry-point window of your app is ready for user interaction.

...