Quite frequently you want to control what happens when your user hits the back button, well this is actually pretty simple to do on Android. I've seen this question pop up several times; so it makes good blog post fodder.
You can either do this totally globally; or on a per page basis. Globally, you just need to add the following code to your app.js file:
Global Event Handler:
// application variable should already be included in the app.js file // Only do this on android if (application.android) { application.android.on(application.AndroidApplication.activityBackPressedEvent, backEvent); } // This does the work on deciding if you want to go back // arg.cancel = true will cancel navigating back function backEvent(args) { if (dontGoBack) { args.cancel = true; } }
You just need to figure out what your criteria is to handle canceling going back.
Individual Page Handler:
Now I personally prefer to put the handler on each page I need it on; so it is a little bit different.
You need to have a pageLoaded and a pageUnloaded event.
// Somewhere at the top var application = require('application'); // Somewhere in your page you need to register your handler exports.pageLoaded = function() { // We only want to register the event in Android if (application.android) { application.android.on(application.AndroidApplication.activityBackPressedEvent, backEvent); } }; // When we navigate away from this page, we need to de-register the handler. exports.pageUnloaded = function() { // We only want to un-register the event on Android if (application.android) { application.android.off(application.AndroidApplication.activityBackPressedEvent, backEvent); } }; // This does your checks to see if you want to go back // setting cancel=true will cancel the back function backEvent(args) { if (iRefuseToGoBack) { args.cancel = true; } }
In your page.xml your "Page" declaration should look like:
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded" unloaded="pageUnloaded">
You might notice in the individual page view version I register and de-register the event. Each time the page is loaded it will register the event, if you don't de-register the event then that event handler will STILL run each time you hit the back button. So it is very important if you are not using a global handler, to register on load, and de-register on unload.
Advanced Global Technique:
There is one other way to do this; I created this technique in my nativescript-orientation plugin and as I was finishing up this post I realized it could apply here and eliminates all the busy work of registering and de-registering handlers on each page but allows you per-page handlers. I'm actually going to switch my apps to this way; because now that I wrote it -- it is my favorite way. 🙂
In your app.js file:
var frame = require('ui/frame'); if (application.android) { application.android.on(application.AndroidApplication.activityBackPressedEvent, backEvent); } function backEvent(args) { var currentPage = frame.topmost().currentPage; if (currentPage && currentPage.exports && typeof currentPage.exports.backEvent === "function") { currentPage.exports.backEvent(args); } }
Then in any page you want to control the back Event you do:
exports.backEvent = function(args) { if (iDontReallyWantToGoBack) { args.cancel = true; } }
Pretty simple you only need to have a single global register; and it checks to see if the current page has a back handler which it will call if it exists.
Have fun, and now we can all stop going back. 😀
What about ios? Is there a way?
Thanks
I'm working on a plugin for this; but not sure when I will be done with it.
I have tried the individual way on a Modal Page. It don`t works like expected.
Are you trying to do a .showModal()? Or some other way?
Its not working on ShowModal page 🙁
Do you have any sample how can we integrate this in nativescript - angular2 project ?
I would think the code would work as-is, since Angular2 is just a wrapper over NS...
Hi Anderson,
Angular way requires minimal changes. As module import and binding events are little different.
Here is the angular way,
import * as application from "application";
ngAfterViewInit() {
if (application.android) {
application.android.on(application.AndroidApplication.activityBackPressedEvent, this.backEvent);
}
}
ngOnDestroy() {
// cleaning up references/listeners.
if (application.android) {
application.android.off(application.AndroidApplication.activityBackPressedEvent, this.backEvent);
}
}
backEvent(args){
if(this.isRefuseToGoBack){
args.cancel = true;
return;
}
}
However i'm facing problem with the isRefuseToGoBack variable, it is always undefined in backEvent. Except this issue its working as expected.
Awesome thanks for the code update of Angular Native. On your this.isRefuseToGoBack issue, did you create a isRefuseToGoBack variable inside your class?
to bind the correct "this" use:
backEvent = (args) => {
if(this.isRefuseToGoBack){
args.cancel = true;
return;
}
}
Thanks for this . How can I user RouterExtension.back() in that handler.
Sorry, I have no idea. I haven't had a chance to investigate Angular2 in context with this design.
args.cancel = true;itest it works on android 4.4,but it does not work on android 5.0.
If you can duplicate this issue; I would recommend you put a new issue up on the NativeScript Github Issues so that it can be fixed in a future version...
Here's what I've done to solve my issue...
My app allows a user to sign in. Once they are in, my client did not want the back button to be used ONLY on the first screen after signing in. This would close the app and force them to re-sign in again. So I only prevented the back button on the first screen (after sign in).
NOTE: I am using Angular in my NativeScript app.
On the screen I wanted to control the back button, I added the following code to the constructor:
this.page.on(Page.loadedEvent, event => {
if (application.android) {
application.android.on(application.AndroidApplication.activityBackPressedEvent, this.backEvent);
}
})
this.page.on(Page.unloadedEvent, event => {
if (application.android) {
application.android.off(application.AndroidApplication.activityBackPressedEvent, this.backEvent);
}
})
I then create a function after my ngOnInit function:
private backEvent(args) {
args.cancel = true;
}
That's it!
NOTE: Don't forget to add the following before your @Component declaration:
import { Page } from "ui/page";
var application = require('application');
Also, your constructor show have...
constructor(private page: Page, ...
Hi,
Is the iOS version ready yet? We need this so badly, appreciate it if you have already finished the iOS version.
Nope, I haven't done anything iOS related to this.
How to close application on back press button using native script?.
The Nativescript-Master-technology plugin has a `exit` and `restart` function. So if you capture the back button, you can call the exit function.
Is there a ts or vanilla js solution ?J
The main code of the article is the JS way to do it.
Three years later, still this is handy!
Shame iOS functionality hasn't yet been added,