From 67efe4c1a932ac6acd20caf497df6978c1b52c90 Mon Sep 17 00:00:00 2001 From: Sokovikov Date: Wed, 23 Mar 2016 12:21:07 -0700 Subject: [PATCH] custom back button handler Summary:sometimes it is nessesary to handle back button specifically for component, by changing its state. For ex. exit from edit mode. Closes https://github.com/facebook/react-native/pull/5062 Differential Revision: D3084590 Pulled By: ericvicenti fb-gh-sync-id: 13a4ea1d64ce725daa5d3af0d629a0c132a3f3d5 shipit-source-id: 13a4ea1d64ce725daa5d3af0d629a0c132a3f3d5 --- Examples/UIExplorer/BackAndroidExample.js | 66 +++++++++++++++++++ Examples/UIExplorer/UIExplorerList.android.js | 4 ++ Libraries/Utilities/BackAndroid.android.js | 28 ++++---- 3 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 Examples/UIExplorer/BackAndroidExample.js diff --git a/Examples/UIExplorer/BackAndroidExample.js b/Examples/UIExplorer/BackAndroidExample.js new file mode 100644 index 000000000..3643f76f6 --- /dev/null +++ b/Examples/UIExplorer/BackAndroidExample.js @@ -0,0 +1,66 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +'use strict'; + +var React = require('react-native'); +var { + Text, + View, + BackAndroid, +} = React; + +var BackAndroidExample = React.createClass({ + + getInitialState: function() { + return { + defaultBackHandler: false + }; + }, + + componentDidMount: function() { + BackAndroid.addEventListener('hardwareBackPress', this._handleBackButton); + }, + + componentWillUnmount: function() { + BackAndroid.removeEventListener('hardwareBackPress', this._handleBackButton); + }, + + _handleBackButton: function() { + if (!this.state.defaultBackHandler) { + this.setState({defaultBackHandler: true}); + return true; + } + + return false; + }, + + render: function() { + return ( + + {this.state.defaultBackHandler ? 'Ok, I\'ll quit.' : 'I won\'t quit.'} + + ); + }, +}); + +exports.title = 'BackAndroid'; +exports.description = 'Custom back button handler'; +exports.examples = [ + { + title: 'Custom back button handler', + render(): ReactElement { return ; } + } +]; diff --git a/Examples/UIExplorer/UIExplorerList.android.js b/Examples/UIExplorer/UIExplorerList.android.js index bb5b13a81..c8c8408c7 100644 --- a/Examples/UIExplorer/UIExplorerList.android.js +++ b/Examples/UIExplorer/UIExplorerList.android.js @@ -102,6 +102,10 @@ const APIExamples = [ key: 'AppStateExample', module: require('./AppStateExample'), }, + { + key: 'BackAndroidExample', + module: require('./BackAndroidExample'), + }, { key: 'BorderExample', module: require('./BorderExample'), diff --git a/Libraries/Utilities/BackAndroid.android.js b/Libraries/Utilities/BackAndroid.android.js index 795380448..b8c997869 100644 --- a/Libraries/Utilities/BackAndroid.android.js +++ b/Libraries/Utilities/BackAndroid.android.js @@ -20,17 +20,19 @@ type BackPressEventName = $Enum<{ backPress: string; }>; -var _backPressSubscriptions = new Set(); +var _backPressSubscriptions = []; RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function() { - var backPressSubscriptions = new Set(_backPressSubscriptions); - var invokeDefault = true; - backPressSubscriptions.forEach((subscription) => { + var propagate = true; + for (var i = _backPressSubscriptions.length - 1; i >= 0; i--) { + var subscription = _backPressSubscriptions[i]; if (subscription()) { - invokeDefault = false; + propagate = false; + break; } - }); - if (invokeDefault) { + } + + if (propagate) { BackAndroid.exitApp(); } }); @@ -60,18 +62,18 @@ var BackAndroid = { addEventListener: function ( eventName: BackPressEventName, handler: Function - ): {remove: () => void} { - _backPressSubscriptions.add(handler); - return { - remove: () => BackAndroid.removeEventListener(eventName, handler), - }; + ): void { + _backPressSubscriptions.push(handler); }, removeEventListener: function( eventName: BackPressEventName, handler: Function ): void { - _backPressSubscriptions.delete(handler); + var index = _backPressSubscriptions.indexOf(handler); + if (index !== -1) { + _backPressSubscriptions.splice(index, 1); + } }, };