正确防止 Flex Mobile 应用程序中的方向更改 [英] Properly preventing orientation change in Flex Mobile app

查看:29
本文介绍了正确防止 Flex Mobile 应用程序中的方向更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有人能够真正让它在 Flex SDK 4.6 中正常工作?

这是一个简短的片段:

<fx:脚本><![CDATA[私有函数 onAddedToStage(event:Event):void {如果(stage.autoOrients){stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING,orientationChanging,false,0,true);}}私有函数orientationChanging(event:StageOrientationEvent):void {if (event.afterOrientation == StageOrientation.DEFAULT || event.afterOrientation == StageOrientation.UPSIDE_DOWN) {event.preventDefault();}}]]></fx:脚本></s:查看>

我想要实现的是在两个方向都支持横向模式,因此如果用户将设备旋转 180 度,屏幕也应该旋转.但是,当用户将设备旋转到纵向之一时,根本不应该有任何动作.相反,我看到导航器操作栏的宽度发生了变化,有时内容是纵向的,因此显然阻止该事件是不够的.我正在使用 Adob​​e 建议的官方"方式,但问题是它运行得不是很好.当然,舞台没有改变,但似乎导航器中的某些东西正在触发,因为您可以看到操作栏宽度发生变化.

我在处理程序方法中将布局边界显式设置为固定宽度取得了一些成功 - 这可以防止更改操作栏宽度,但这只是一个临时解决方案 - 如果视图是过渡或其他一些重绘的主题 - 它会再次以错误的尺寸渲染.好像下面有什么东西在告诉它处于纵向模式,即使我试图阻止它.

在你用诸如autoOrient = false"之类的愚蠢想法引爆之前,不要.这显然不是这个问题的解决方案.显然这是 Flex SDK 的一个错误 - 有没有人找到修复它的方法或稳定的解决方法?

显然其他人遇到了类似的问题:
- http://forums.adobe.com/message/3969531(主要话题是关于别的东西,但请阅读魔法机器人的评论)
- http://forums.adobe.com/message/4130972

解决方案

我不确定这是否正确,我最后是不是做错了什么,但经过一番挣扎,我找到了这个一个是稳定的解决方案:

私有函数 onAddedToStage(event:Event):void {如果(stage.autoOrients){stage.removeEventListener(StageOrientationEvent.ORIENTATION_CHANGING,orientationChanging);stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGING,orientationChanging,false,100,true);}}私有函数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() - 现在,我们是第一个处理该事件的人,我们无法阻止此事件在此特定场景中进一步向上发送.

这一起使方向无法完美工作 - 对我来说,横向和反向横向(rotated_left,rotated_right)正在工作和过渡,而纵向模式根本不影响视图.

现在,这里存在危险 - 您可能希望在离开视图时移除侦听器(在过渡动画结束、视图停用或其他情况下),因为 stopImmediatePropagation 将阻止在应用程序的其他部分处理该事件.

我希望 Adob​​e(现在实际上是 Apache)能够仔细研究这个问题并追踪我的解决方案.

编辑

此解决方案还存在最后一个问题,即如果应用程序在设备处于 DEFAULT 或 UPSIDE_DOWN 方向时启动,在这种情况下应用程序将处于纵向模式.

要解决此问题,解决方案是在 addedToStage 处理程序中更改纵横比:

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

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

这篇关于正确防止 Flex Mobile 应用程序中的方向更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆