PDA

Просмотр полной версии : кнопка Back на андроиде, preventDefault и flex


PainKiller
17.07.2014, 17:22
Ситуация такая. Есть views, с разными состояниями, которые меняются при работе пользователя в приложении. Воодушевившись этим постом (http://grindheadgames.com/handling-button-air-android/), я решил сделать так, чтобы при нажатии кнопки Back, пользователь возвращался бы не к предыдущему view, а к предыдущему состоянию компонента. Для этого в главном классе приложения я написал следующий код:

//срабатывает при запуске приложения
private function onAdded(e:Event):void
{
NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, false, 0, true);
...
}

private function onKeyDown(e:KeyboardEvent):void
{
trace ("onKeyDown main");
trace (navigator.activeView.id);
if (e.keyCode == Keyboard.BACK)
{
if ((navigator.activeView.id == "SomeState" && navigator.activeView.currentState == "SelectOneList") ||
(navigator.activeView.id == "SomeState" && navigator.activeView.currentState == "SelectSpinners") ||
(navigator.activeView.id == "SomeState" && navigator.activeView.currentState == "SelectManyList") )
{
e.stopImmediatePropagation();
e.preventDefault();
//trace (e.cancelable);
navigator.activeView.currentState = "default";
trace (e.isDefaultPrevented() + " prevented");
trace(navigator.activeView.currentState);
trace(navigator.activeView.id);
}
}
}


cancelable для евента я проверил, тут все нормально. Так вот в дебаггере видно, как все четко отрабатывает, трейсится нужное состояние и вью. Но визуально, перехвата события не происходит, все равно все откатывается на предыдущий вью. Единственный вариант решения который я вижу - переделать состояния на вьюхи, но это получится геморно и некрасиво. В общем жду советов, заранее спасибо.

Добавлено через 4 минуты
Да еще пробовал насильно заталкивать нужный view вот этой строчкой в обработчике события:

navigator.pushView(views.SomeView);

но это дает только белый экран.

Добавлено через 10 минут
вообще много чего пробовал, менял местами строчки и т.д., пришел к парадоксальному выводу, что именно добавление этой строкиnavigator.activeView.currentState = "default";
возвращает предыдущий view, без нее все перехватывается.

Добавлено через 19 часов 21 минуту
В общем путем экспериментов нащупал решение, оно почему то по разному ведет себя в эмуляторе и на реальном аппарате, привожу код:
в главном классе приложения

NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, false, 0, true);

...

private function onKeyDown(e:KeyboardEvent):void
{

if (e.keyCode == Keyboard.BACK)
{
if ((navigator.activeView.id == "SomeState" && navigator.activeView.currentState == "SelectOneList") ||
(navigator.activeView.id == "SomeState" && navigator.activeView.currentState == "SelectSpinners") ||
(navigator.activeView.id == "SomeState" && navigator.activeView.currentState == "SelectManyList") )
{
trace(navigator.activeView.currentState);
trace(navigator.activeView.id);

}
}
}

В вьюхе, в которой по кнопке Back нужно менять стейты:

<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
...
currentState="default" backKeyPressed="backKeyPressedHandler(event)">

private function backKeyPressedHandler(e:FlexEvent):void
{
trace("backKeyPressedHandler");
trace(e.type); //backKeyPressed
trace(e.target);
trace(currentState);
if(currentState == "SelectOneList" || currentState == "SelectSpinners" || currentState == "SelectManyList")
{
e.preventDefault();
e.stopImmediatePropagation();
this.currentState = "default";

}

}

Так вот, какие странности в работе. В эмуляторе это решение срабатывает только со 2-го нажатия клавиши (только со второго раза срабатывает обработчик backKeyPressedHandler). Без обработчика в главном классе (а глядя на код можно подумать что он не нужен) в эмуляторе у меня это решение вообще не работало. На телефоне вроде все работает нормально, с первого нажатия, но честно говоря до конца эту логику я не понимаю, буду рад любым комментариям.

alatar
20.07.2014, 12:39
В "главном" классе в обработчике необходимости нет. Во view уберите строку:
e.stopImmediatePropagation();

PainKiller
21.07.2014, 16:22
Спасибо за отклик. Сделал так как вы посоветовали. В вашей версии на телефоне работает, в эмуляторе нет. Но в любом случае проблема решена.