Is anyone able to actually make it work properly in Flex SDK 4.6?
Here\'s a short snippet :
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.
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);
}