React Native - Android BackHandler - How to implement this.OnMainScreen and this.goBack - android

I have splash screen on my apps, so I want to exit the apps when we click android back button from the main page (not go back to splash screen). So I want to implement this method from react-native tutorial.
if (!this.onMainScreen()) {
this.goBack();
return true;
}
return false;
Is there anyone can help me how to implement onMainScreen(), and goBack() functions?
Thank you for the help.

you should be able to use this function
function getCurrentRouteFromState(navigationState): NavigationRouteConfigMap {
const route = navigationState.routes[navigationState.index];
// dive into nested navigators
if (route.routes) {
return getCurrentRouteFromState(route);
}
return route;
}
pass it your navigation state and access the routeName member on the resulting object:
let screenName = getCurrentRouteFromState(state).routeName then you can compare the screen name with your main screen name and decide what to do.

So, On your main page(I think which is your Main.js)
import { BackHandler } from 'react-native';
componentWillMount(){
BackHandler.addEventListener('hardwareBackPress', function() {
BackHandler.exitApp();
});
}

Related

How to add a page to navigation history to prevent app from exiting?

I'm still rather new to Ionic 4. I'm making an App that receives push notification. The navigation inside the app works like this:
Home page -> Detail page
Every time the user taps on the notification, the app will open and navigates to Detail page. The navigation works but since the navigation history is empty, if the user taps on the hardware back button, the app exits. I want it to redirect the user to Home page instead.
How do I achieve this in Ionic 4? is there any way to push a page to navigation history? I have read the documentation but couldn't find anything about this. The closest was probably NavCtrl.push() but it's no longer usable in Ionic 4.
Thank you.
There may be an easier way to do this but the following approach is a very flexible one because it'd allow you to run any custom logic when the user wants to go back from the page shown after a push notification or a deep link is opened.
Please take a look at this StackBlitz demo.
Please notice that in the demo, I'm redirecting to the DetailsPage as soon as the app is loaded because of the following code from the app-routing.module file:
{
path: "",
redirectTo: "/details/1?fromDeepLink=true", // <-- here!
pathMatch: "full"
}
Anyway, the important part happens in the DetailsPage. There, you need to handle what happens when the user tries to go back using a) the back button from the header and b) the physical back button from Android devices
The code is pretty self-explanatory, but basically in that page I'm looking for the fromDeepLink query string param, and if it's true, the app will register a custom action for both the back button from the header and for the physical back button from Android devices.
The custom action sets the HomePage as the root page, but sets the animationDirection parameter to be 'back'. That way it'd look like the user is going back to that page even if we're actually adding it to the navigation stack.
It's important to notice that this custom handler is being removed as soon as the user leaves the page so that we don't affect the default behaviour of the back button in any other pages.
import { Component, OnInit, ViewChild } from "#angular/core";
import { ActivatedRoute } from "#angular/router";
import { IonBackButtonDelegate, NavController, Platform, ViewDidEnter, ViewWillLeave } from "#ionic/angular";
import { Subscription } from "rxjs";
#Component({
selector: "app-details",
templateUrl: "./details.page.html",
styleUrls: ["./details.page.scss"]
})
export class DetailsPage implements OnInit, ViewDidEnter, ViewWillLeave {
#ViewChild(IonBackButtonDelegate, { static: false })
public backButton: IonBackButtonDelegate;
public itemId: number;
public fromDeepLink: boolean = false;
private unregisterBackButtonAction: Subscription;
constructor(
private platform: Platform,
private route: ActivatedRoute,
private navCtrl: NavController,
) {}
ngOnInit() {
const itemIdParam = this.route.snapshot.paramMap.get("itemId");
const fromDeepLinkParam = this.route.snapshot.queryParamMap.get('fromDeepLink');
this.itemId = +itemIdParam;
this.fromDeepLink = fromDeepLinkParam
? fromDeepLinkParam.toLocaleLowerCase() === 'true'
: false;
}
ionViewDidEnter() {
if(this.fromDeepLink) {
this.initializeCustomBackButtonAction()
}
}
ionViewWillLeave() {
if(this.fromDeepLink) {
this.removeCustomBackButtonAction();
}
}
private initializeCustomBackButtonAction(): void {
const leavingCallback = () => {
console.log('Using custom back button action');
this.navCtrl.navigateRoot('/home', { animationDirection: 'back' });
};
// Override the back button from the header
if (this.backButton) {
this.backButton.onClick = leavingCallback;
}
// Override the physical back button from Android devices
this.unregisterBackButtonAction = this.platform.backButton.subscribeWithPriority(10, leavingCallback);
}
private removeCustomBackButtonAction(): void {
this.unregisterBackButtonAction?.unsubscribe();
}
}
Please also notice that by default the ion-back-button is not shown if there's no page before the current page in the navigation stack, so in the demo I'm setting the defaultHref property like this:
<ion-back-button defaultHref></ion-back-button>
I'm leaving it empty because the component is actually going to override what this back button does with my custom back button action. But the defaultHref needs to be added to the template, otherwise the back button won't be shown.

Pop to root on tabclick FreshTabbedNavigationContainer on android

Consider a tabbar with "home" and "profile" buttons, when i click on either i switch between two pages, on the "home" page the user can navigate multiple times up in the navigationstack still having the focus on the "home" tab indicating that this is where the user came from.
Now, on iOS whenever the user clicks on "home" from high up in the navigationstack the user is popped to root and all is well, this is not the case on android however, on android the user has to pop one page at a time by clicking on the backbutton to get to the root.
Is this intended behavior, am i doing something wrong, does someone have a clue as to what i can do to get the desired behavior?
This is the intended behavior between iOS and Android .
If you need to make the Android has the same effect with iOS, you need to custom TabbedPageRenderer to achieve that. And the bottom tab bar effect can custom a FreshTabbedNavigationContainer . Last, we will use MessagingCenter to send message to Forms to pop to Root Page.
For example, CustomFreshTabbedNavigationContainer class:
public class CustomFreshTabbedNavigationContainer : FreshTabbedNavigationContainer
{
public CustomFreshTabbedNavigationContainer()
{
On<Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);
MessagingCenter.Subscribe<object>(this, "Hi", (sender) =>
{
// Do something whenever the "Hi" message is received
PopToRoot(true);
});
}
}
Used in App.xaml.cs:
public App()
{
InitializeComponent();
var container = new CustomFreshTabbedNavigationContainer();
container.AddTab<FirstPageModel>("Home", default);
container.AddTab<ProfilePageModel>("Profile", default);
MainPage = container;
}
Now we will create a CustomTabbedPageRenderer in Android:
public class CustomTabbedPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemSelectedListener
{
public CustomTabbedPageRenderer(Context context) : base(context)
{
}
int previousItemId = 0;
bool BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
{
base.OnNavigationItemSelected(item);
if (item.IsChecked)
{
if (previousItemId != item.ItemId)
{
previousItemId = item.ItemId;
}
else
{
Console.WriteLine("ok");
MessagingCenter.Send<object>(this, "Hi");
}
}
return true;
}
}
The effect:
Note: If need to have the same effect with the top Tabbar in Android, there is different code in CustomTabbedPageRenderer. You can have a look at this discussion.

Ionic 4 android hardware back button and toolbar back not working in same flow

I came across an issue in my android app which i have developed using ionic 4.
My scenario is if i navigate through pages and came back using toolbar back button and again navigate to another pages and came back using android hardware back button then the pages i navigated back using toolbar back button shows in middle while using hardware back button.
Page A->B->C and then on toolbar back button C->B->A
Again page navigate A->D->E and then using hardware back button page navigate E->D->B->C->B->A
Unable to maintain state.
My Code
In app.component.ts constructor
this.router.events.subscribe(event => {
const url = this.router.url //current url
if (event instanceof NavigationEnd) {
const isCurrentUrlSaved = this.navLinksArray.find((item) => { return item === url });
if (!isCurrentUrlSaved) this.navLinksArray.push(url);
}
});
ngAfterViewInit() {
this.backButtonSubscription = this.platform.backButton.subscribe(() => {
if (this.router.url === '/tabs/home') {
navigator['app'].exitApp();
} else {
if (this.navLinksArray.length > 1) {
this.navLinksArray.pop();
const index = this.navLinksArray.length - 1;
const url = this.navLinksArray[index];
this.navCtrl.navigateBack(url);
}
}
});
}
}
Thanks in advance.
I think, this.navCtrl.navigateBack(url); is pushing pages again like behavior is asynchronous just assuming.
Why dont you just pop the navigated page, lets say you have a generic function
ngAfterViewInit() {
static BackButton(platform:Platform,navCtrl:NavController){
platform.registerBackButtonAction(() => {
navCtrl.pop();
}, 0)
}
}
and from the navigated page component just call, which must have
constructor(public navCtrl: NavController,public platform:Platform){}, defined and then call generic method BackButton(this.platform,this.navCtrl) in same navigated page component.

How to identify back button event in Xamarin cross-platform (Xamarin.Forms)

Is there any way to know when the 'back' button event on the 'Android phone' is pressed? I'd like to exit the game and add few functionality to it when this button is pressed in Xamarin.Forms.
I googled a bit regarding this, but I got articles regarding Xamarin.Android Back button but not for Xamarin.Forms.
As I am relatively new to Xamarin.Forms, please help me out
public override void OnBackPressed()
{
//base.OnBackPressed();
}
Same thing I want in Xamarin.Forms. Need some assistance, guys.
If you mean Xamarin.Forms by "Xamarin Cross Platform", there is a OnBackButtonPressed event that you can use. As seen on that documentation:
Event that is raised when the hardware back button is pressed. This
event is not raised on iOS.
Simply override this event on your NavigationPage and you're ready to go:
protected override bool OnBackButtonPressed()
{
// Do your magic here
return true;
}
Good luck!
In my xamarin forms app you need to find the NavigationStack of the current Page if you are using master page:
public bool DoBack
{
get
{
MasterDetailPage mainPage = App.Current.MainPage as MasterDetailPage;
if (mainPage != null)
{
bool doBack = mainPage.Detail.Navigation.NavigationStack.Count > 1 || mainPage.IsPresented;
//top level of page and the Master menu isn't showing
if (!doBack)
{
// don't exit the app only show the Master menu page
mainPage.IsPresented = true;
return false;
}
else
{
return true;
}
}
return true;
}
}

AngularJS back button

I'm working on making an Android app using Phonegap and AngularJS. I'm attempting to create a button to be used as both a "cancel" and a "back" button, that will essentially just hit the browser's 'back' button.
Here's some sample HTML for the cancel button:
cancel
And here is the controller for that page, with the goBack() button:
function NewOccasionCtrl($scope, $window) {
$scope.$window = $window;
$scope.goBack = function() {
$window.history.back();
};
}
This throws no errors, but also doesn't work... the emulator remains on the same page. Without the $scope.$window = $window it throws an error. I was hoping to achieve a functional 'back' button without having to create/use a directive, because as far as I understand those then implement templating and things I don't need/want.
Is there a way to do this? Thanks
I went with using a Directive to make the back functionality reusable. Here is my final code:
HTML:
<a href back-button>back</a>
Javascript:
app.directive('backButton', function(){
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('click', goBack);
function goBack() {
history.back();
scope.$apply();
}
}
}
});
I had an issue like this using phonegap and angular, $window.history.back() would not work. So I created a workaround.
$scope.urlHistory = [];
$scope.$on('$routeChangeSuccess', function () {
if ($location.$$absUrl.split('#')[1] !== $scope.urlHistory[$scope.urlHistory.length - 1]) {
$scope.urlHistory.push($location.$$absUrl.split('#')[1]);
}
});
$scope.goBack = function () {
$scope.urlHistory.pop();
$location.path($scope.urlHistory[$scope.urlHistory.length - 1]);
};
Hope this help someone else.

Categories

Resources