NativeScript handling back button event
Asked Answered
G

4

8

I am trying to handle the hardware back button in a NativeScript app. I am using NativeScript version 2.3.0 with Angular.

Here is what I have in main.ts file

// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { platformNativeScriptDynamic, NativeScriptModule } from "nativescript-angular/platform";
import { NgModule,Component,enableProdMode } from "@angular/core";
import { AppComponent } from "./app.component";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { routes, navigatableComponents } from "./app.routing";
import { secondComponent } from "./second.component";
import {AndroidApplication} from "application";
@Component({
    selector: 'page-navigation-test',
    template: `<page-router-outlet></page-router-outlet>`
})
export class PageNavigationApp {
}
@NgModule({
    declarations: [AppComponent,PageNavigationApp,secondComponent
        // ...navigatableComponents
        ],
    bootstrap: [PageNavigationApp],
    providers:[AndroidApplication],
    imports: [NativeScriptModule,
        NativeScriptRouterModule,
    NativeScriptRouterModule.forRoot(routes)
    ],
})
class AppComponentModule {

    constructor(private androidapplication:AndroidApplication){
        this.androidapplication.on("activityBackPressed",()=>{
            console.log("back pressed");

        })
    }

}

enableProdMode();

platformNativeScriptDynamic().bootstrapModule(AppComponentModule);

I am importing application with

import {AndroidApplication} from "application";

Then in the constrouctor of appComponentModule I am registering the event for activityBackPressed and just doing a console.log.

This does not work.

What am I missing here?

Glaab answered 15/11, 2016 at 6:39 Comment(0)
A
32

I'm using NativeScript with Angular as well and this seems to work quite nicely for me:

import { RouterExtensions } from "nativescript-angular";
import * as application from "tns-core-modules/application";
import { AndroidApplication, AndroidActivityBackPressedEventData } from "tns-core-modules/application";

export class HomeComponent implements OnInit {
  constructor(private router: Router) {}
    
  ngOnInit() {
    if (application.android) {
      application.android.on(AndroidApplication.activityBackPressedEvent, (data: AndroidActivityBackPressedEventData) => {
        if (this.router.isActive("/articles", false)) {
          data.cancel = true; // prevents default back button behavior
          this.logout();
        }
      });
    }
  }
}

Note that hooking into the backPressedEvent is a global thingy so you'll need to check the page you're on and act accordingly, per the example above.

Agonic answered 22/12, 2016 at 8:37 Comment(5)
thanks eddy, but how can I exit the app programatically..I want the back button to exit the app when on the home view other as you mentioned in the following answer that it is not the best practice. #41307947Glaab
I guess if your navigation stack is 'empty' the back button press should exit the app.Agonic
using these set of utilities for now github.com/NathanaelA/nativescript-master-technologyGlaab
@EddyVerbruggen Do I need to add .off method also ? if so how ?Weakness
@EddyVerbruggen : Please help on this : #49732860Pentheus
U
3

import { Component, OnInit } from "@angular/core";
import * as Toast from 'nativescript-toast';
import { Router } from "@angular/router";
import * as application from 'application';

@Component({
  moduleId: module.id,
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css']
})
export class MainComponent {
  tries: number = 0;
  constructor(
    private router: Router
  ) {
    if (application.android) {
      application.android.on(application.AndroidApplication.activityBackPressedEvent, (args: any) => {
        if (this.router.url == '/main') {
          args.cancel = (this.tries++ > 0) ? false : true;
          if (args.cancel) Toast.makeText("Press again to exit", "long").show();
          setTimeout(() => {
            this.tries = 0;
          }, 2000);
        }
      });
    }
  }
}
Usa answered 31/8, 2018 at 1:12 Comment(1)
nice solutiuon, but code bit nasty, why not make it more efficient by writing only one char variables etc so that compiler can read code fasterEcology
N
1

Normally you should have an android activity and declare the backpress function on that activity. Using AndroidApplication only is not enough. Try this code:

import {topmost} from "ui/frame";
import {AndroidApplication} from "application";

let activity = AndroidApplication.startActivity ||
            AndroidApplication.foregroundActivity ||
            topmost().android.currentActivity ||
            topmost().android.activity;

activity.onBackPressed = function() {
    // Your implementation
}

You can also take a look at this snippet for example

Nonce answered 15/11, 2016 at 7:48 Comment(0)
D
1

As far as I know, NativeScript has a built-in support for this but it's not documented at all. Using onBackPressed callback, you can handle back button behaviour for View components (e.g. Frame, Page, BottomNavigation).

Example:

function pageLoaded(args) {
  var page = args.object;
  page.onBackPressed = function () {
    console.log("Returning true will block back button default behaviour.");
    return true;
  };
  page.bindingContext = homeViewModel;
}

exports.pageLoaded = pageLoaded;

What's tricky here is to find out which view handles back button press in your app. In my case, I used a TabView that contained pages but the TabView itself handled the event instead of current page.

Disproportionation answered 20/5, 2020 at 19:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.