Phonegap landscape not detecting orientation for 90 and -90 - ios

I have a problem getting my iOS app to use landscape mode.
I'm new to phonegap, iOS, mac, and most of this stuff but have been searching the web for a few days now and I need help.
I'm using xcode 5, phonegap 2.3.0, and my intended target is iPhone iOS 7.
I have an app that is in production, and I need to give it some support for landscape.
In specific situations it should be possible to tilt the phone and get a better view.
I found this code:
window.addEventListener('orientationchange', doOnOrientationChange,true);
function doOnOrientationChange(e)
{
alert('orientation event fire');
switch(e.orientation)
{
case -90:
case 90:
alert('landscape');
break;
default:
alert('portrait');
break;
}
}
I can also use window.orientation instead of e.orientation.
This seams to be the popular way of handling this stuff.
For some reason the alert "orientation event fire" is only called when the phone is turned 180 and back to 0. No event is happening at 90 or -90.
I set the supported interface orientations, in xcode, to all 4 possibilities.
And in my index.html I have:
<meta name="viewport" content="user-scalable=yes, width=device-width" />
I can get the app to start in landscape mode but not change into it once the app is running.
It can change back to portrait mode just fine.
For some reason the phone is not telling me when it is at 90 and -90.
I read that it is not phonegap that is handling the rotation, but the browser that is used by phonegap. This is the behavior that I am looking for as I would like the browser to resize and rotate everything for me when the phone is tilted.
Also i'm reluctant to update phonegap as I have read many post about it handling rotation bad after version 2.3.0
Any ideas ??
EDIT:
Sometimes the answer comes to you, only once you asked the question on a forum.
The problem in my case was that another developer in my company had added:
function shouldRotateToOrientation(interfaceOrientation) {
return app.shouldRotateToOrientation( interfaceOrientation );
}
To my index.js file.
Apparently the shouldRotateToOrientation function is one that phonegap will look for in the code, and if it is there use to, limit the screen rotation.
I tried writing the following:
function shouldRotateToOrientation(interfaceOrientation) {
return true;//(1 === interfaceOrientation);
}
And everything worked fine.... Or one thing remains
The next problem is to find the current direction.
Apparently the value passed to shouldRotateToOrientation will indicate the current orientation. (The interfaceOrientation in my case)
Some write 1 means portrait and 2,3,4 refers to the other orientations.
Some write it returns 0, 90, -90, 180. (The last one I found to be true in my case.)
However it calls the function 4 times at each orientation shift.
So putting a console.log into the function will result in 4 lines being printed each time the phone is tilted.
The order in which the lines are printed are the same in each case, so no way of determining which way the phone is actually turning.
Someone gave this as a solution:
function changeOrientation() {
console.log(window.orientation);
}
window.onorientationchange = function () {
//Need at least 800 milliseconds
setTimeout(changeOrientation, 800);
}
But this is only called when the screen actually change orientation and I need something to tell me which way the phone is turning, so I can decide if I will allow an orientation change.
Also it is a bit annoying that it should be necessary to wait for 800 milliseconds.
Any idea how to get the current actual orientation of the phone. Not the orientation the app is rendered at??
EDIT:
I ended up using:
function shouldRotateToOrientation(newOrientation) {
return window.app.supportLandscape || !(interfaceOrientation%180);
}
For limiting the screen even though the newOrientation value is all over the place it still works. The window.app.supportLandscape is the one is set in my code where I want to support landscape or not. The !(interfaceOrientation%180) part allows me to rotate back to portrait in all cases.
If i go to a screen that is allowed to be landscape.
I turn the phone and go into landscape mode.
I then press the back button and go back to the page that should only be in portrait mode.
I see this page in landscape mode (cannot be helped)
I turn the phone back to portrait mode and the screen is now in portrait mode again, and locked to this mode.
The next problem I am facing is that on the devices landscape screen is not rerendered.
The graphics turn but it does not scale to fit the screen.
This behavior is only when I use Archive to generate an .ipa file, and deploy it through iTunes.
When launching directly from xcode 5 to the device or to any simulator, the graphics will fit to scale in landscape mode.
I found a post saying that the problem was xcode using different setups to generate .ipa files as opposed to launching the code. This is true as xcode uses debug when launching and release when archiving.
I tried to set archive mode to use debug but same problem.
I tried to set run to release but it still worked fine.
Any ideas ???

Use native code as plugin ad call it using javascript. also add it in config.xml. and in CDViewController change Autorotate - return NO. If you want a detailed solution then let me know. I have solved this same condition.
Update : my Solution
Create a new js file as ScreenOrientation.js and insert the below code,
var ScreenOrientation = {
//alert(orientation);
callScreenOrientationNative: function(success,fail,orientation) {
return Cordova.exec( success, fail,
"ScreenOrientation",
"screenorientationFunction",
[orientation]);
}
};
and add the above file in index.html as below,
<script type="text/javascript" src="ScreenOrientation.js"></script>
Add the below function in any added js file(in my project i have added a script.js file to add common functions),
function callScreenOrientation(orientation) {
ScreenOrientation.callScreenOrientationNative(nativePluginResultHandler,nativePluginErrorHandler,orientation);
}
function nativePluginResultHandler (result) {
}
function nativePluginErrorHandler (error) {
}
In config.xml add the below under feature name,
<!-- Screen Orientation custom plugin to display reports page. -->
<feature name="ScreenOrientation">
<param name="ios-package" value="ScreenOrientation"/>
</feature>
Under Plugins add (For cordova < 3.0),
<plugins>
<plugin name="ScreenOrientation" value="ScreenOrientation" />
</plugins>
On Cordova projects > Plugins right click and select new file, then from iOS select Cocoa touch then Select objective-C Class and click next, in class name insert "ScreenOrientation" and in Subclass of "CDVPlugin" and click next and click create.
Enter the below in ScreenOrientation.h,
#import <Cordova/CDV.h>
#interface ScreenOrientation : CDVPlugin
- (void) screenorientationFunction:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
#end
Enter the below in ScreenOrientation.m,
#import "ScreenOrientation.h"
#implementation ScreenOrientation
- (void) screenorientationFunction:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
[arguments pop];
NSString *orientation = [arguments objectAtIndex:0];
if ( [orientation isEqualToString:#"LandscapeLeft"] ) {
NSLog(#"Landscape Left");
[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeLeft];
}
else if ( [orientation isEqualToString:#"LandscapeRight"] ) {
NSLog(#"Landscape Right");
[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight];
}
else if ( [orientation isEqualToString:#"Portrait"] ) {
NSLog(#"Portrait");
[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait];
}
else if ( [orientation isEqualToString:#"PortraitUpsideDown"] ) {
NSLog(#"Portrait upSide Down Left");
[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortraitUpsideDown];
}
}
#end
In Cordova project click search and search for "shouldAutoRotate and find the below and change the return, by default it will be 'YES' change it to 'NO'.
CDVViewController.m
- (BOOL)shouldAutorotate
{
return NO;
}
And in project settings, in Device orientations check all options (not important though),
Project Settings > Device orientation > Tick all 4 options.
and call it from your project like this,
callScreenOrientation('LandscapeLeft');
callScreenOrientation('LandscapeRight');
callScreenOrientation('Portrait');
callScreenOrientation('PortraitUpsideDown');

In Xcode 5, select your target, click on the Info tab and make sure you've got the appropriate 'Supported Interface Orientations' selected. In my case, the Phonegap CLI produced a project that had only Portrait added to the orientation list -- even though I specified Landscape in config.xml
Screenshot:
http://i.stack.imgur.com/Bi8RC.png

Related

React native orientation is not working || locking on IOS

I created an app with React-native. All pages I made are designed for portrait mode except 1 page. The page accessibility comes from a button onPress then navigates to the page, so I can't lock orientation on Xcode
I installed this package and I can run it on android perfectly
import Orientation from 'react-native-orientation';
When I tried it on IOS simulator on every page it can turns orientation to landscape.
I put this line in every pages componentdidmount but nothing changes.
componentDidMount() {
Orientation.lockToPortrait()
...
}
What should I do?
Hey again #masterAvatarr,
I believe that this is what you're looking for, if you need something else please explain it to me :) We can make it happen.
I made a simple example for you.
https://github.com/WrathChaos/react-native-portrait-locker-example
I use React Native Orientation Locker Library
The important parts are:
Make sure that you linked the library manually (check AppDelegate.m)
You need to make a logic for unlocking and lock the portrait mode depends on your use-case
Please take a look at HomeScreen and DetailScreen
import Orientation from "react-native-orientation-locker";
React.useEffect(() => {
const unsubscribe = navigation.addListener("focus", () => {
// The screen is focused
// Call any action
Orientation.unlockAllOrientations();
Orientation.lockToPortrait();
});
// Return the function to unsubscribe from the event so it gets removed on unmount
return unsubscribe;
}, [navigation]);
Note: There is a little GIF Demo on the Github Repo

App doesn't work in Portrait mode, can I stop it from rotating? iPad

I'm developing a temporary web app for the iPad. It's really just a stop-gap until a proper mobile solution can be devised for this particular product.
One issue is this app works and looks perfect in Landscape, but in Portrait mode, the dimensions just don't fit.
I'm sure this is a horrible usability crime to even ask such a question, but is there any sort of convention for prohibiting a web app from rotating to Portrait mode?
I'm not looking for an examples of code, I'm just wondering if anything like this exists.
No, there isn't an option. After all html is all about dynamic display of information. Just define the elements of your webapp proper and it will look fine.
You can use the orientation change function to check for the orientation and then show a image or div stating the user that webapp can be opened only in Landscape mode.
window.addEventListener('orientationchange', function(event) {
if (window.orientation == 90 || window.orientation == -90)
{
/* Hiding the Message div */
}
else
{
/* Show a div in Portrait Asking users to switch orientation to Landscape */
}
});

Orientation mode as landscape for only one screen - iPhone

Im developing an application using Titanium which is compatible for iPhone. I'm navigating between 4 views.
1st View (Portrait) ---> 2nd View (Landscape) --> 3rd View (Portrait) ---> 4th View (Portrait)
SO I have 3 Portrait views in my application and I used Tiapp.xml and add
<orientations device="iphone">
<orientation>Ti.UI.PORTRAIT</orientation>
</orientations>
For 2nd View I used following code ;
var winCheckInLogin = Ti.UI.createWindow({
backgroundColor : "black",
orientationModes : [Titanium.UI.LANDSCAPE_LEFT, Titanium.UI.LANDSCAPE_RIGHT],
navBarHidden : true, // Hides the native title bar
});
winCheckInLogin.addEventListener("open", function() {
Titanium.UI.orientation = Titanium.UI.LANDSCAPE_LEFT;
});
But for the loading time 2nd View appear on Portrait mode after I rotate my device it keep it as Landscape. I need to load it as Landscape mode and lock that screen as it is.
Please help me to solve this.
Thanks a lot
Gayan,
Using different orientation modes for a single app in iPhone is not recommended. Please read Orientation design principles
Apple's Developer documentation says: "People expect to use your
app in different orientations, and it’s best when you can fulfill that
expectation." In other words, don't look at handling orientation as a
bother but an opportunity.
Apple further recommends that when choosing to lock or support
orientation, you should consider following these principles:
On iPhone/iPod Touch – Don't mix orientation of windows within a single app; so, either lock orientation for the whole app, or react to orientation changes.
On iPhone – don't support the portrait-upside-down orientation because that could leave the user with their phone upside-down when receiving a phone call.
However, if you want to use different orientations, just add the following to your tiApp.xml under <orientations device="iphone"> tag
<orientations device="iphone">
<orientation>Ti.UI.LANDSCAPE_LEFT</orientation>
<orientation>Ti.UI.LANDSCAPE_RIGHT</orientation>
</orientations>
This will do the trick for you!!
http://docs.appcelerator.com/titanium/latest/#!/api/Titanium.UI.Window-property-orientationModes
In your tiapp.xml
<orientations device="iphone">
<orientation>Ti.UI.PORTRAIT</orientation>
<orientation>Ti.UI.LANDSCAPE_LEFT</orientation>
<orientation>Ti.UI.LANDSCAPE_RIGHT</orientation>
</orientations>
For all Windows (and not views), be sure to add the property of that window as:
orientationModes: [Ti.UI.PORTRAIT]
for Portrait-only Windows,
and for lanscape-only:
orientationModes: [Ti.UI.LANDSCAPE_LEFT, Ti.UI.LANDSCAPE_RIGHT]
That should do the trick you're looking for.

Properly preventing orientation change in Flex Mobile app

Is anyone able to actually make it work properly in Flex SDK 4.6?
Here's a short snippet :
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
addedToStage="onAddedToStage(event)"
title="Title">
<fx:Script>
<![CDATA[
private function onAddedToStage(event:Event):void {
if (stage.autoOrients) {
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging, false, 0, true);
}
}
private function orientationChanging(event:StageOrientationEvent):void {
if (event.afterOrientation == StageOrientation.DEFAULT || event.afterOrientation == StageOrientation.UPSIDE_DOWN) {
event.preventDefault();
}
}
]]>
</fx:Script>
</s:View>
What I'm trying to achieve is to support Landscape mode in both orientations, so if user turns the device 180 degress, the screen should also rotate. But there should be no action at all, when user rotates the device to one of portrait orientations. Instead, I'm seeing width changes to navigator action bar and sometimes content in portrait orientations, so apparently preventing the event is not enough. I'm using the "official" way Adobe suggests, but the problem is that it's not working very well. Granted, the stage does not change, but it seems that there's something firing in navigator anyway, since you can see the action bar width changing.
I had some success with explicitly setting layoutbounds to fixed width in handler method - this prevents changing the actionbar width, but it's only a temporary solution - if the view is a subject to a transition, or some other redraw - it will again render with bad sizes. As if there was something below that was telling it that it's in portrait mode, even though I'm trying to prevent it.
Before you detonate with some silly ideas like "autoOrient = false", don't. It's clearly not a solution for this problem. Obviously it's a bug with Flex SDK - did anyone find a way to fix it or a stable workaround?
EDIT: apparently others bumped into similar issue:
- http://forums.adobe.com/message/3969531 (the main topic is about something else, but read magic robots's comment)
- http://forums.adobe.com/message/4130972
I'm not sure if this is the right one, did I do something wrong in the end, but after a lot of struggle, I've found this one to be stable solution:
private function onAddedToStage(event:Event):void {
if (stage.autoOrients) {
stage.removeEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging);
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging, false, 100, true);
}
}
private function orientationChanging(event:StageOrientationEvent):void {
event.stopImmediatePropagation();
if (event.afterOrientation == StageOrientation.DEFAULT || event.afterOrientation == StageOrientation.UPSIDE_DOWN) {
event.preventDefault();
}
}
First thing to note is that addedToStage fires few times (2-3) in mobile application. I don't know why, there's no addChild in my code, obviously. Maybe the AIR runtime does something else. So, to avoid adding unnecessary amount of handlers, the common technique is to remove handler first - it won't do anything, if such handler is not yet registered, but if there is, it will remove it, which will maintain the handler count on 1.
Second thing is the priority of the event - it won't work on 0, it has to be set on something big, to launch before stuff in AIR runtime.
Last thing - event.stopImmediatePropagation() - now, that we're the first to handle the event, we cant prevent this event to be sent further up in this particular scenario.
This together makes the orientation preventing working perfectly - for me the landscape and the reversed landscape (rotated_left, rotated_right) were working and transitioning, while portrait modes did not affect the view at all.
Now, there's danger here - you might want to remove the listener upon leaving the view (on transition animation end, view deactivate or something), because stopImmediatePropagation will prevent the event to be handled in other parts of your application.
I hope Adobe (or Apache now, actually) will take a closer look at this problem and trace my solution.
EDIT
There remaisn a last issue with this solution, which is if application starts while device is in DEFAULT or UPSIDE_DOWN orientation, in this case application will be in portrait mode.
To fix this, a solution is to change Aspect Ratio within addedToStage handler:
if(Stage.supportsOrientationChange) {
stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
}
So I had the same problem you had. I think I finally figured out the solution. Heres what I did:
<s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
...blahblahblah...
width="1024"/>
protected function tabbedviewnavigatorapplication2_applicationCompleteHandler(event:FlexEvent):void {
stage.autoOrients=true;
preventOrient();
}
private function preventOrient():void {
if (stage.autoOrients) {
stage.removeEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging);
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING, orientationChanging, false, 100, true);
}
}
private function orientationChanging(event:StageOrientationEvent):void {
if(event.afterOrientation == StageOrientation.DEFAULT || event.afterOrientation == StageOrientation.UPSIDE_DOWN || event.afterOrientation == StageOrientation.UNKNOWN) {
event.preventDefault();
}
}
Worth noting is that in the application complete handler I set stage.autoOrients to true because in the app.xml file I have it set to false, due to having a splash screen and not wanting users to re-orient the screen during that time. Really the only thing I did different is account for the StageOrientation.UNKNOWN and prevent whatever that would do, set the width to 1024(for the iPad screen, might be different for other tablet devices) in the main mxml file, and removed the stopimmediatepropagation. Hope this helps.

Xcode force enable application rotation

I am working on an iPad/iPhone tab-bar based application. I have about 30 class files and need to enable rotation in the app, so that iPad users can view at any orientation. As far as I know, every class needs rotation to be enabled by using the following:
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return YES;
}
However, I have some UIViewControllers created and displayed completely in a single class file, and as far as I know you cannot enable it for that type.
Is there a way I can enable global rotation for the app? I have tried in Info.plist. is there something that can be added to the AppDelegate to enable global rotation?
Btw: I have already tried adding returning YES for rotation in every class file.
Thanks in advance,
Baharini
In Xcode on the Project Navigator click on the project name. Now on center view on the Summary tab, you can see the iPad\iPhone Development Info in this part there is Supported Device Orientations. You can set all of them for supporting any orientation!
I hope it be useful for you!

Resources