React Native Android Hardware Back button not working properly - android

LoginScreen.js
this.props.navigator.push({
screen: "auxxa.LandingScreen",
passProps: { login: true },
overrideBackPress: true,
navigatorStyle: {
navBarHidden: true
}
});
LandingScreen.js
constructor(props) {
super(props);
this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
// this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
this.state = {
size: { width, height },
tileData: null,
isLoading: true,
user_id: null,
refetching: false,
access_token: null
};
}
componentWillMount() {
BackHandler.addEventListener(
"hardwareBackPress",
this.handleBackButtonClick
);
}
handleBackButtonClick() {
console.log("check login " + this.props.login);
if (this.backPressed && this.backPressed > 0) {
if (this.props.login) {
console.log("login");
RNExitApp.exitApp();
} else {
console.log("root");
this.props.navigator.popToRoot({ animated: false });
return false;
}
}
this.backPressed = 1;
this.props.navigator.showSnackbar({
text: "Press one more time to exit",
duration: "long"
});
return true;
}
componentDidMount() {
BackHandler.removeEventListener(
"hardwareBackPress",
this.handleBackButtonClick
);
}
I used react-native-navigation from Wix for my app nevigation purpose.Here I have attached login screen and landing screen.after successful login app navigate to landing screen.after that I click back button It will return to login screen.I need to avoid that.How can I do that thing? I tried to exit from the app.But it also not working properly.
Please help me if some one know this.Thanks in advanced.

Use this call in handleBackButtonClick function and why are you removing the listener in componentDidMount ?
this.props.navigator.resetTo({ screen: 'example.ScreenThree'})
.

Uncomment this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this)); on your constructor to listen to navigation events
and add the navigationEvent listener method
onNavigatorEvent(event: NavigatorEvent) {
if (event.type === 'NavBarButtonPress') {
if (event.id === 'skill_information') {
// Add here whatever you would like to do (this.handleBackButtonClick() for example)
}
}

Related

Ionic 3: Back Button Hardware Event Handler Can't Determine Overlay Views

I have an ionic 3 application and I modified the functionality of the hardware back button. It works on pages but it cannot determine whether overlay views like modals and alert dialog boxes are present or not.
Here is my code
this.platform.registerBackButtonAction(() => {
let nav = app._appRoot._getActivePortal() || app.getActiveNav();
let activeView = nav.getActive().instance;
if (activeView != null) {
if (nav.canGoBack()) {
if (activeView instanceof MultiRegistrationOne || activeView instanceof MultiRegistrationTwo || activeView instanceof MultiRegistrationThree) {
// do something
} else {
nav.pop();
}
} else if (activeView.isOverlay) {
activeView.dismiss();
} else {
let alert = this.alertCtrl.create({
title: 'Ionic App',
message: 'Do you want to close the app?',
buttons: [{
text: 'Cancel',
role: 'cancel',
handler: () => {
console.log('Application exit prevented!');
}
},
{
text: 'Close',
handler: () => {
this.platform.exitApp();
}
}]
});
alert.present();
}
}
});
I hope someone can help me with this. Thank you in advance 😊
declare a variable :viewController:ViewController
then in your page or app.components.ts , modify your back button handle to be like the
this.platform.registerBackButtonAction(() => {
try{
this.viewController.dismiss()
}
catch(e){
console.log("error");
}
});
I solved it using MD. Riyas' answer here: Solution

Navigating between components reloads all components in navigator routes

I've read somewhere that when you use any navigator from the react-navigation package and if you implement redux; every component in the navigators' routes will be reloaded (i.e componentWillRecieveProps)
However, I've got two pages where the user can login
export const MainScreenTabNavigator = TabNavigator({
Start: {
screen: Start,
navigationOptions: {
title: 'Start',
},
},
},{
tabBarPosition: "bottom",
tabBarOptions: {
activeTintColor: '#222',
labelStyle: {
color: '#ddd',
},
style: { backgroundColor: '#333' },
}
});
export const AppNavigator = StackNavigator({
Main: {
screen: MainScreenTabNavigator, // Nested tab navigator
},
Login: {
screen: Login,
navigationOptions: {
title: 'Aanmelden',
}
},
Camera: {
screen: AppCamera,
navigationOptions: {
title: 'Camera',
}
}
}, {
mode: 'modal',
headerMode: 'none',
});
The login screen is initially shown to the user. It has a form where the user can enter it's credentials manually and a button that navigates to the camera where the user can scan a QR code with login credentials.
In both cases the user dispatches a login action.
Both the login page and the camera page listen to the same prop changes:
componentWillReceiveProps(nextProps) {
if (nextProps.account.loginSuccess) {
this.props.navigation.dispatch(NavigationActions.navigate({ routeName: 'Start' }));
} else {
if (nextProps.account.loginError) {
Toast.showLongBottom(nextProps.loginError);
}
}
this.setState({spinnerVisible: false});
}
The app successfully navigates to 'Start' but when it does both the Login and Camera page are reloaded, causing an infinite loop into componentWillReceiveProps and infinitely navigates to 'Start' over and over again.
This is my navigation reducer:
function nav(state = initialNavState, action) {
const nextState = AppNavigator.router.getStateForAction(action, state);
// Simply return the original `state` if `nextState` is null or undefined.
return nextState || state;
}
What can I do to prevent this behavior?
Well,
As a temporary solution I introduced another boolean into the nav state:
function nav(state = initialNavState, action) {
let nextState = null;
if (action.type === 'Navigation/NAVIGATE' && action.routeName === 'Start') {
nextState = {...AppNavigator.router.getStateForAction(action, state), authenticated: true};
} else {
nextState = AppNavigator.router.getStateForAction(action, state);
}
// Simply return the original `state` if `nextState` is null or undefined.
return nextState || state;
}
I use authenticated to check if the login or camera component should navigate to start after logging in.
It works but it still feels like I'm missing something.

React Navigation + Redux close App on Back Pressed

After converting the app to redux, my react-navigation got some problem. Previously, before integrating with redux, when I press back button (Physical button) react-navigation back to the previous screen. After integrating with redux, the back button will close the app. But, it's still working with goBack() function.
I'm following the guide: https://reactnavigation.org/docs/guides/redux
And read some code from here : https://github.com/react-community/react-navigation/tree/master/examples/ReduxExample
And, this is my Navigator configuration
export const AppNavigator = StackNavigator(
{
Home: { screen: HomeScreen },
ChatDetail: { screen: ChatDetail },
PulsaDetail: { screen: PulsaDetailScreen },
Pulsa: { screen: Pulsa }
},
{
headerMode: 'none',
}
)
class AppWithNavigation extends Component {
render(){
return(
<AppNavigator navigation={ addNavigationHelpers({
dispatch: this.props.dispatch,
state: this.props.nav,
})} />
)
}
}
const mapStateToProps = (state) => ({
nav: state.nav
})
export default connect(mapStateToProps)(AppWithNavigation)
EDIT: It's can be done with manual handle & dispatch back action, but it's can't do it automaticlly? just like before using redux?
BackHandler.addEventListener('hardwareBackPress',() => {
this.props.goBack()
return true
})
After post Github issue in react-navigation repository, I got the answer.
Should add manually the back listener on top of screen / component
// App.js
import { BackAndroid } from 'react-native'
// [...]
componentDidMount() {
BackAndroid.addEventListener('backPress', () => {
const { dispatch, nav } = this.props
if (shouldCloseApp(nav)) return false
dispatch({ type: 'Back' })
return true
})
}
componentWillUnmount() {
BackAndroid.removeEventListener('backPress')
}
// [...]
https://github.com/react-community/react-navigation/issues/2117
https://github.com/react-community/react-navigation/issues/117
UPDATE:
https://facebook.github.io/react-native/docs/backhandler

How to listen Android hardware back button in ionic

I try to listen android hardware back button,but it is no effect.
main code:
.run(['$ionicPlatform','$ionicHistory',function($ionicPlatform,$ionicHistory) {
$ionicPlatform.ready(function() {
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
$ionicPlatform.registerBackButtonAction(function (e) {
e.preventDefault();
$ionicHistory.nextViewOptions({
disableAnimate: true
});
$ionicHistory.viewHistory().backView.go();
return false;
}, 100);
}])
My running environment is mobile browser.Android version 4.4.2
UPDATE: I'm no longer using this as it was unreliable. Additionally, in the latest Ionic release, app.ts is now app.component.ts.
For Ionic 2, check out my blog post on how to fix this. Should also work for Ionic 1, as it's only calling a cordova listener:
http://www.codingandclimbing.co.uk/blog/ionic-2-android-back-button-13
and here's the actual post info:
In your app.ts, do the following to get the back button working as expected (mostly!):
initializeApp() {
this.platform.ready().then(() => {
this.registerBackButtonListener();
});
}
registerBackButtonListener() {
document.addEventListener('backbutton', () => {
var nav = this.getNav();
if (nav.canGoBack()) {
nav.pop();
}
else {
this.confirmExitApp(nav);
}
});
}
confirmExitApp(nav) {
let confirm = Alert.create({
title: 'Confirm Exit',
message: 'Really exit app?',
buttons: [
{
text: 'Cancel',
handler: () => {
console.log('Disagree clicked');
}
},
{
text: 'Exit',
handler: () => {
navigator.app.exitApp();
}
}
]
});
nav.present(confirm);
}
getNav() {
return this.app.getComponent('nav');
}
Note:
If you get errors about app not being a property of navigator:
1) Add a typings folder to your app root: e.g. app/typings
2) Add a file called: pluginshackyhacky.d.ts
3) Add for properties you need extended for TypeScript to compile.:
interface /*PhoneGapNavigator extends*/ Navigator {
app: any;
}
4) Add the pluginshackyhacky.d.ts to the compile in the tsconfig.json:
"files": [
"app/app.ts",
"app/typings/pluginshackyhacky.d.ts",
"app/typings/phonegap.d.ts"
]
You can see that I've also included the phonegap.d.ts file which includes a lot of missing properties/variables that allows TypeScript to compile without errors.
Hope this helps anyone having this problem.
Cheers.
may be this could help you.
$state.$current.name == "";var backbutton=0;
$ionicPlatform.registerBackButtonAction(function (event) {
if (($state.$current.name == "app.intro") ||
($state.$current.name == "app.main.home") ||
($state.$current.name == "app.account")) {
if(backbutton==0){
backbutton++;
window.plugins.toast.showLongBottom('Press again to exit');
$timeout(function(){backbutton=0;},3000);
}else{
navigator.app.exitApp();
}
console.log("one");
}else if($state.$current.name == "app.welcome.takeControl") {
console.log("two");
$state.go("app.main.home");
}else{
console.log("three");
navigator.app.backHistory();
}
}, 100);

Exit application from android hardware back button in phonegap

Is there a way to show a confirmation popup when you press the hardware back button in android devices to exit the phonegap/ionic application?
In the current status, my app keep going to the previous state upon clicking the back button.
Is there a way to exit the app when you press the back button no matter where you are on, in the application?
I found this piece of code but it did not seem to work:
$ionicPlatform.registerBackButtonAction(function() {
var confirmPopup = $ionicPopup.confirm({
title: 'Sign Out Confirm',
template: 'Are you sure you want to Logout?'
});
confirmPopup.then(function(res) {
if (res) {
$rootScope.rootScopeUserTransactionPassword = null;
$state.go('app.playlists');
} else {
console.log('You are not sure');
}
});
}, 100);
Try this:
document.addEventListener('backbutton', function(event){
event.preventDefault(); // EDIT
navigator.app.exitApp(); // exit the app
});
I hope it helps you.
It will ask you before exit in stipulated timestamp : Press back button again to exit. If it's dashboard page then it will ask whether to Log out?
I hope it will solve your problem.
.run(function($rootScope, $ionicPlatform, $ionicHistory){
$ionicPlatform.registerBackButtonAction(function(e) {
if ($ionicHistory.currentView().stateName == 'dashboard') {
Dialogs.showConfirm('Do you want to logout?', function(buttonIndex) {
if (buttonIndex == 1)
User.clear();
}, 'Logout', ['Yes', 'No']);
} else
if ($rootScope.backButtonPressedOnceToExit) {
ionic.Platform.exitApp();
} else if ($ionicHistory.backView()) {
$ionicHistory.goBack();
} else {
$rootScope.backButtonPressedOnceToExit = true;
window.plugins.toast.showShortCenter(
"Press back button again to exit",
function(a) {},
function(b) {}
);
setTimeout(function() {
$rootScope.backButtonPressedOnceToExit = false;
}, 2000);
}
e.preventDefault();
return false;
}, 101);
});
The following close the app if we hit back button on Android device in "Login" screen.
In your app.js you maybe have something like this:
app.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$stateProvider.state('login', {
url : '/',
}).state('login', {
url : '/login',
views : {
contentView : {
templateUrl : 'login.html',
controller : 'LoginCtrl'
}
}
});
So all you have to do is add this method in the same file:
app.run(function($ionicPlatform) {
$ionicPlatform.registerBackButtonAction(function() {
if ($state.current.name == "login") {
navigator.app.exitApp();
}
}, 100);
});
Note that "login" it the state name which mentioned in the app.config

Categories

Resources