Правильное предотвращение изменения ориентации в приложении Flex Mobile - PullRequest
4 голосов
/ 17 января 2012

Может ли кто-нибудь на самом деле заставить его работать должным образом в 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, но проблема в том, что он работает не очень хорошо.Конечно, этап не меняется, но, похоже, что-то в навигаторе все-таки срабатывает, так как вы можете видеть изменение ширины панели действий.

У меня был некоторый успех с явной установкой границ компоновки на фиксированную ширину в методе обработчикаэто предотвращает изменение ширины панели действий, но это только временное решение - если представление является объектом перехода или какой-либо другой перерисовки - оно снова будет отображаться с неверными размерами.Как будто внизу было что-то, что говорило, что это в портретном режиме, хотя я пытаюсь это предотвратить.

Прежде чем взорваться с какими-то глупыми идеями, такими как "autoOrient = false", не надо.Это явно не решение этой проблемы.Очевидно, это ошибка Flex SDK - кто-нибудь нашел способ ее исправить или стабильный обходной путь?

РЕДАКТИРОВАТЬ: очевидно, что другие столкнулись с аналогичной проблемой:
- http://forums.adobe.com/message/3969531 (основная тема о чем-то другом, но прочитайте комментарий магических роботов)
- http://forums.adobe.com/message/4130972

Ответы [ 2 ]

6 голосов
/ 18 января 2012

Я не уверен, что это правильно, я сделал что-то не так в конце, но после долгой борьбы я нашел это стабильное решение:

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 () - теперь, когда мы первыми обработаем событие, мы не можем предотвратить дальнейшее отправку этого события в данном конкретном сценарии.

Это вместе делает ориентацию препятствующей работе идеально - для меня пейзаж и перевернутый пейзаж (rotated_left, rotated_right) работали и переходили, в то время как режимы портрета вообще не влияли на вид.

Теперь здесь есть опасность - вы можете захотеть удалить слушателя при выходе из представления (в конце анимации перехода, деактивации представления или чего-то еще), потому что stopImmediatePropagation предотвратит обработку события в других частях вашего приложения..

Надеюсь, Adobe (или сейчас Apache, собственно) внимательнее посмотрит на эту проблему и проследит мое решение.

РЕДАКТИРОВАТЬ

Повторно возникает последняя проблема с этим решением, которая возникает, если приложение запускается, когда устройство находится в ориентации DEFAULT или UPSIDE_DOWN, в этом случае приложение будет в портретной ориентации.mode.

Чтобы исправить это, решение состоит в том, чтобы изменить Aspect Ratio внутри обработчика AddedToStage:

   if(Stage.supportsOrientationChange) {
         stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
    }
1 голос
/ 30 мая 2012

Итак, у меня была та же проблема, что и у вас.Я думаю, что я наконец-то нашел решение.Вот что я сделал:

<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 и предотвращение того, что бы это ни делало, установите ширину 1024 (для экрана iPad может отличаться для других планшетных устройств) в главном файле mxml и удалите распространение,Надеюсь, это поможет.

...