正确防止Flex Mobile应用程序中的方向更改

时间:2012-01-17 19:55:54

标签: ios flex mobile air orientation

是否有人能够在Flex SDK 4.6中实际使其正常工作?

这是一个简短的片段:

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

我想要实现的是在两个方向都支持横向模式,因此如果用户将设备旋转180度,屏幕也应该旋转。但是,当用户将设备旋转到纵向方向之一时,根本不应该执行任何操作。相反,我看到导航器操作栏的宽度更改,有时纵向方向的内容,所以显然阻止事件是不够的。我正在使用Adobe建议的“官方”方式,但问题是它运行得不好。当然,舞台不会改变,但似乎导航器中还有一些东西在射击,因为你可以看到动作条的宽度在变化。

我在处理程序方法中明确地将layoutbounds设置为固定宽度取得了一些成功 - 这可以防止更改操作栏宽度,但它只是一个临时解决方案 - 如果视图是转换的主题,或者其他一些重绘 - 它将再次渲染大小不好。好像有下面的东西告诉它它处于纵向模式,即使我试图阻止它。

在引爆一些愚蠢的想法之前,例如“autoOrient = false”,不要。这显然不是解决这个问题的方法。显然这是Flex SDK的一个错误 - 有没有人找到解决方法或稳定的解决方法?

编辑:显然其他人遇到了类似的问题:
- http://forums.adobe.com/message/3969531(主题是关于其他事情,但阅读魔术机器人的评论)
- http://forums.adobe.com/message/4130972

2 个答案:

答案 0 :(得分:6)

我不确定这是否是正确的,最后我做错了什么,但经过多次努力,我发现这个是稳定的解决方案:

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(); 
    }   
}  

首先要注意的是,在移动应用程序中,addedToStage会激发几次(2-3)。我不知道为什么,显然我的代码中没有addChild。也许AIR运行时会做其他事情。因此,为了避免添加不必要的处理程序,常见的技术是首先删除处理程序 - 它不会做任何事情,如果这样的处理程序尚未注册,但如果存在,它将删除它,这将保持处理程序计数在1.

第二件事是事件的优先级 - 它不能在0上工作,必须在大事件上设置,在AIR运行时之前启动。

最后一件事 - event.stopImmediatePropagation() - 现在,我们是第一个处理事件的人,我们无法防止在这个特定场景中进一步发送此事件。

这一起使得方向防止完美地工作 - 对我来说,景观和颠倒的景观(rotate_left,rotating_right)正在工作和转换,而肖像模式根本不影响视图。

现在,这里存在危险 - 您可能希望在离开视图时移除侦听器(在转换动画结束时,查看停用或其他内容),因为stopImmediatePropagation将阻止在应用程序的其他部分处理事件。

我希望Adobe(或现在的Apache)会仔细研究这个问题并追踪我的解决方案。

修改

此解决方案的最后一个问题是,如果应用程序在设备处于DEFAULT或UPSIDE_DOWN方向时启动,则此应用程序将处于纵向模式。

要解决此问题,解决方法是在addedToStage处理程序中更改Aspect Ratio:

   if(Stage.supportsOrientationChange) {
         stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
    }

答案 1 :(得分:1)

所以我遇到了同样的问题。我想我终于找到了解决方案。继承人我做了什么:

<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(); 
    }
}

值得注意的是,在应用程序完整处理程序中,我将stage.autoOrients设置为true,因为在app.xml文件中我将其设置为false,因为它具有启动画面并且不希望用户在重新定向屏幕期间那时。实际上我唯一不同的就是占用StageOrientation.UNKNOWN并防止无论做什么,在主mxml文件中将宽度设置为1024(对于iPad屏幕,可能与其他平板电脑设备不同),并删除stopimmediatepropagation 。希望这会有所帮助。