Preventing Back Button Default When Navigating Views in Flex Hero Mobile Application
来源:互联网 发布:献成分血的危害知乎 编辑:程序博客网 时间:2024/06/04 20:03
转载:http://swfhead.com/blog/?p=884
Preventing Back Button Default When Navigating Views in Flex Hero Mobile Application
Items Covered: Flex Hero Views, Hardware Back Button on Android Devices
Flex/AIR Version: 4.5 (Hero), AIR Android 2.5
Difficulty Level: Beginner
Prerequisite Knowledge: How Views work in Flex 4.5 Mobile Application
Sample Application: ViewNavFix.apk (I would show this in browser but it is a mobile app, so you’ll need to download and either run it on a device or in Emulator)
Sample Application Files: ViewNavFix.fxp (You will need Flash Builder Burrito)
Desired Interaction:
You want to prevent the hardware BACK button from firing a popView() event when in a View. Maybe this is to bring up a confirmation dialog or perform some other action. Then, go back to the previous view when another button is pressed.
Problem:
Simply using preventDefault() when listening to the Keyboard.BACK down (or up) event does not actually prevent the popView() event. It seems as though there is a bug where NativeApplication still hears when the Keyboard (hardware buttons) are pressed, so your application will always preform the default action when the hardware buttons are pressed. This happens whenever there is not anything on stage in focus. In addition, the event listeners can not be fully removed from within a view.
Solution:
You must prevent default in the main Application file, as well as within any View. In essence you MUST handle all the hardware keys’ listeners yourself, in every state of the application. You must also have something on stage in focus to prevent the default action of the hardware buttons.
ViewNavFix.mxml
First, I had to preventDefault on the BACK button in the main Application file. This means I will then need to handle the back button interactions. See the code:
[codesyntax lang="actionscript3" lines_start="1"]
<?xml version="1.0" encoding="utf-8"?><s:MobileApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" applicationComplete="init()" firstView="views.ViewNavFixHome"><fx:Declarations><!-- Place non-visual elements (e.g., services, value objects) here --></fx:Declarations><fx:Script><![CDATA[private function init():void{globalKeyListeners();}protected function globalKeyListeners():void{NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, handleHardwareKeysDown);NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_UP, handleHardwareKeysUp);}private function handleHardwareKeysDown(e:KeyboardEvent):void{if(e.keyCode == Keyboard.BACK){trace("back button down");e.preventDefault();}}private function handleHardwareKeysUp(e:KeyboardEvent):void{if(e.keyCode == Keyboard.BACK){trace("back button up");e.preventDefault();}}]]></fx:Script></s:MobileApplication>
[/codesyntax]
ViewNavFixHome.mxml
Since I have to handle the Back button my own now in the Home View, I have to preventDefault() and perform my desired action. I am listening for the Back button from NativeApplication to exit(), and pushing to a second View with navigator.pushView();. And since I am doing this I have to add the event listeners on viewActivate(). For some reason the listeners bubble to the previous next view so I have to remove them on viewDeactivate().
[codesyntax lang="actionscript3" lines_start="1"]
<?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" viewActivate="homeInit(event)" viewDeactivate="destroyHardwareKeyListeners(event)" title="Home"><fx:Script><![CDATA[import mx.events.FlexEvent;private function homeInit(e:FlexEvent):void{trace("homeInit");enableHardwareKeyListeners();}private function enableHardwareKeyListeners():void{NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, handleHardwareKeysDown, false, 0);NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_UP, handleHardwareKeysUp, false, 0);}private function destroyHardwareKeyListeners(e:FlexEvent):void{trace("destroyHardwareKeyListeners");NativeApplication.nativeApplication.removeEventListener(KeyboardEvent.KEY_DOWN, handleHardwareKeysDown);NativeApplication.nativeApplication.removeEventListener(KeyboardEvent.KEY_UP, handleHardwareKeysUp);}private function handleHardwareKeysDown(e:KeyboardEvent):void{if(e.keyCode == Keyboard.BACK){e.preventDefault();NativeApplication.nativeApplication.exit();}}private function handleHardwareKeysUp(e:KeyboardEvent):void{if(e.keyCode == Keyboard.BACK){e.preventDefault();NativeApplication.nativeApplication.exit();}}protected function goToNewView(e:MouseEvent):void{navigator.pushView(SecondView);}]]></fx:Script><fx:Declarations><!-- Place non-visual elements (e.g., services, value objects) here --></fx:Declarations><s:Label left="40" right="40" top="40" height="30" text="To go to a new View, click the button."/><s:Button top="100" width="200" label="GO" click="goToNewView(event)" horizontalCenter="0"/></s:View>
[/codesyntax]
SecondView.mxml
So now comes the View where we need to I need to actually block the Back button from popView() to go back to the previous View. This was the biggest pain. Again, I’m adding the event listeners on viewActivate() and removing them on viewDeactivate(). The Back button can now catch the user from leaving the View and goes to a Confirmation state where the user can then either stay in the View to continue working or go back. In order for the Back button to not call popView() something needs to be in focus (preventDefault doesn’t catch it otherwise). So I’m just focusing something, anything, on stage whenever the Initial State is entered.
[codesyntax lang="actionscript3" lines_start="1"]
<?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" title="SecondView" viewActivate="secondViewInit(event)"viewDeactivate="destroyKeyListeners(event)"><fx:Script><![CDATA[import mx.events.FlexEvent;protected function secondViewInit(e:FlexEvent):void{trace("secondViewInit");enableKeyListeners();}private function enableKeyListeners():void{trace("enableKeyListenersInit");NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN, handleHardwareKeysDown);NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_UP, handleHardwareKeysUp);}private function destroyKeyListeners(e:FlexEvent):void{trace("destroyKeyListenersInit");NativeApplication.nativeApplication.removeEventListener(KeyboardEvent.KEY_DOWN, handleHardwareKeysDown);NativeApplication.nativeApplication.removeEventListener(KeyboardEvent.KEY_UP, handleHardwareKeysUp);}private function handleHardwareKeysDown(e:KeyboardEvent):void{trace("handleHardwareKeysDown");if(e.keyCode == Keyboard.BACK){currentState = "ConfirmState";e.preventDefault();}}private function handleHardwareKeysUp(e:KeyboardEvent):void{trace("handleHardwareKeysUpInit");if(e.keyCode == Keyboard.BACK){currentState = "ConfirmState";e.preventDefault();}}// !----- Initial State -----! //private function goBackButtonClick(e:MouseEvent):void{currentState = "ConfirmState";}private function focusSomething(e:FlexEvent):void{trace("focusSomethingElse");mainLabel.setFocus();}// !------ ConfirmState -----! //private function noButtonClick(e:MouseEvent):void{trace("noButtonClick");currentState = "InitialState";}private function yesButtonClick(e:MouseEvent):void{trace("yesButtonClick");navigator.popView();}]]></fx:Script><fx:Declarations><!-- Place non-visual elements (e.g., services, value objects) here --></fx:Declarations><s:states><s:State name="InitialState" enterState="focusSomething(event)" /><s:State name="ConfirmState" /> <!-- enterState="focusSomethingElse(event)"/> --></s:states><!-- InitialState --><s:Label includeIn="InitialState" id="mainLabel" left="10" right="10" top="40" textAlign="center" text="Try to Hit the Back Button, 
or the button below" /><s:Button includeIn="InitialState" id="goBackButton" top="100" label="Go Back" horizontalCenter="0" click="goBackButtonClick(event)" /><!-- ConfirmState --><s:Label includeIn="ConfirmState" id="confirmLabel" left="10" right="10" top="40" textAlign="center" text="Are you sure you want to go back?" /><s:Button includeIn="ConfirmState" id="noButton" top="100" left="30" width="200" label="STAY" click="noButtonClick(event)" /><s:Button includeIn="ConfirmState" id="yesButton" top="100" right="30" width="200" label="LEAVE" click="yesButtonClick(event)"/></s:View>
[/codesyntax]
Conclusion:
In order to fully prevent the Back button default action, you MUST fully handle the hardware button yourself. This also gives you the most control over the hardware buttons if you want to do something other than the default action – like bringing up a dialog. While your handling them, you MUST
1. Listen for the Events when the View is activated.
2. Remove the Events when the View is deactivated.
3. Handle the closing of your app appropriately.
4. preventDefault in the main application file AND every subsequent View.
A bit of overkill for something that sounds so simple, sure. But, frankly it was easier than rolling my own ViewNavigator. This is beta software (Flex 4.5 is anyway) so I can’t complain too much, but this should be much easier to do.
Happy Flashing!
- Preventing Back Button Default When Navigating Views in Flex Hero Mobile Application
- Beginning a WPF/MVVM application: Navigating between views
- Changing the default skins on a Button control in Flex
- Mobile Development in 2013: A Look Back
- Reload the site when reached via browsers back button
- Disable Back Button in Browser using JavaScript
- pure actionscript3 button in flex ,
- Switching to other views in a doc-view application
- Preventing SQL Injections in ASP
- Preventing Hangs in Windows Applications
- Advances in Mobile and Wireless Communications: Views of the 16th IST Mobile and Wireless Communicat
- Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
- Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
- Tip: Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
- Tip: Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
- Tip: Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
- Tip: Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
- Tip: Use View.isInEditMode() in your custom views to skip code when shown in Eclipse
- [Linux][2012-09-27] Linux nm && ldd 命令
- linux crontab命令参数及用法详解--linux自动化定时任务cron
- 链表相邻元素翻转,如a->b->c->d->e->f-g,翻转后变为:b->a->d->c->f->e->g
- highcharts日期型X轴示例2-采用arryList输出categories和确定x值
- 如何在Eclipse中用JDBC连接Sql Server 2005
- Preventing Back Button Default When Navigating Views in Flex Hero Mobile Application
- mysql常用修改表的命令
- 研究称HTML5或需更多时间才能战胜本地化应用
- 网络小计1
- Linux Shell编程入门
- Netty实现原理浅析
- <zz>conjugate gradient共轭梯度方法及matlab推导
- 导出多个表格到EXCEL或者ET的JavaScript代码
- MySQL查询乱码的解决方法