Search code examples
ioscordovalandscape

Phonegap landscape not detecting orientation for 90 and -90


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 ???


Solution

  • 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');