Как обращаться с кнопкой возврата на Ionic 2

Как я могу обработать действие кнопки «Назад» на Ionic 2?

Я хочу знать, что делать, в зависимости от того, какая страница отображается пользователю.

Я не нашел хорошего ответа на этот вопрос, но через некоторое время я решил, что это способ сделать это. Я собираюсь поделиться со всеми вами.

благодаря

    Вот как я это сделал:

    В каждом компоненте страницы я создал функцию backButtonAction() , которая будет выполнять пользовательский код для каждой страницы.

    Код:

     import { Component } from '@angular/core'; import { Platform, NavController, ModalController } from 'ionic-angular'; import { DetailsModal } from './details'; @Component({ selector: 'page-appointments', templateUrl: 'appointments.html' }) export class AppointmentsPage { modal: any; constructor(private modalCtrl: ModalController, public navCtrl: NavController, public platform: Platform) { // initialize your page here } backButtonAction(){ /* checks if modal is open */ if(this.modal && this.modal.index === 0) { /* closes modal */ this.modal.dismiss(); } else { /* exits the app, since this is the main/first tab */ this.platform.exitApp(); // this.navCtrl.setRoot(AnotherPage); <-- if you wanted to go to another page } } openDetails(appointment){ this.modal = this.modalCtrl.create(DetailsModal, {appointment: appointment}); this.modal.present(); } } 

    И в app.component.ts я использовал метод platform.registerBackButtonAction для регистрации обратного вызова, который будет вызываться каждый раз при нажатии кнопки «Назад». Внутри я проверяю, существует ли функция backButtonAction на текущей странице и вызывает ее, если она не существует, просто перейдите на вкладку main / first.

    Это можно было бы упростить, если им не нужно было выполнять индивидуальные действия для каждой страницы. Вы можете просто выйти или выйти из приложения.

    Я сделал это так, потому что мне нужно было проверить, был ли модаль открыт на этой конкретной странице.

    Код:

      platform.registerBackButtonAction(() => { let nav = app.getActiveNav(); let activeView: ViewController = nav.getActive(); if(activeView != null){ if(nav.canGoBack()) { nav.pop(); }else if (typeof activeView.instance.backButtonAction === 'function') activeView.instance.backButtonAction(); else nav.parent.select(0); // goes to the first tab } }); 

    если текущая страница является первой вкладкой, приложение закрывается (как определено в методе backButtonAction ).

    Ionic Последняя версия 3.xx app.component.ts import { Platform, Nav, Config, ToastController} from 'ionic-angular'; файл import { Platform, Nav, Config, ToastController} from 'ionic-angular';

     constructor(public toastCtrl: ToastController,public platform: Platform) { platform.ready().then(() => { //back button handle //Registration of push in Android and Windows Phone var lastTimeBackPress=0; var timePeriodToExit=2000; platform.registerBackButtonAction(() => { // get current active page let view = this.nav.getActive(); if(view.component.name=="TabsPage"){ //Double check to exit app if(new Date().getTime() - lastTimeBackPress < timePeriodToExit){ this.platform.exitApp(); //Exit from app }else{ let toast = this.toastCtrl.create({ message: 'Press back again to exit App?', duration: 3000, position: 'bottom' }); toast.present(); lastTimeBackPress=new Date().getTime(); } }else{ // go to previous page this.nav.pop({}); } }); }); } 

    Я использовал ответы отсюда и других источников, чтобы выполнить то, что мне нужно. Я заметил, что при создании приложения для производства (-prod) этот подход не работает, поскольку JS угадает и упрощает:

     this.nav.getActive().name == 'PageOne' 

    Из-за этого я использую следующий оператор «if»:

     view.instance instanceof PageOne 

    Таким образом, окончательный код выглядит следующим образом:

     this.platform.ready().then(() => { //Back button handling var lastTimeBackPress = 0; var timePeriodToExit = 2000; this.platform.registerBackButtonAction(() => { // get current active page let view = this.nav.getActive(); if (view.instance instanceof PageOne) { if (new Date().getTime() - lastTimeBackPress < timePeriodToExit) { this.platform.exitApp(); //Exit from app } else { let toast = this.toastCtrl.create({ message: 'Tap Back again to close the application.', duration: 2000, position: 'bottom', }); toast.present(); lastTimeBackPress = new Date().getTime(); } } else if (view.instance instanceof PageTwo || view.instance instanceof PageThree) { this.openPage(this.pages[0]); } else { this.nav.pop({}); // go to previous page } }); }); 

    Согласно документации Ionic 2 RC.4 отсюда :

    Вы можете использовать метод registerBackButtonAction(callback, priority) API Platform чтобы зарегистрировать действие нажатием кнопки «Назад».

    Событие кнопки «Назад» запускается, когда пользователь нажимает кнопку обратной связи на собственной платформе, также называемую «аппаратной» кнопкой возврата. Это событие используется только в приложениях Cordova, работающих на платформах Android и Windows. Это событие не запускается на iOS, так как iOS не поставляется с аппаратной кнопкой возврата в том же смысле, что и устройство Android или Windows.

    Регистрация действия кнопки «Назад» и установка приоритета позволяют приложениям контролировать, какое действие следует вызывать при нажатии кнопки «Назад». Этот метод решает, какой из зарегистрированных действий кнопки кнопки имеет наивысший приоритет и должен быть вызван.

    Параметры:

    • callback : функция, вызываемая при нажатии кнопки «Назад», если это зарегистрированное действие имеет наивысший приоритет.
    • priority : Number, чтобы установить приоритет для этого действия. Выполняется только самый высокий приоритет. По умолчанию 0

    Возвраты: Функция : Функция, которая при вызове будет отменять действие кнопки «Назад».

    Я смог выполнить это в том случае, если мы просто устанавливаем корневые страницы …

     import {Component, ViewChild, Injector} from '@angular/core'; import {Platform, MenuController, Nav, App, IonicApp, NavController} from 'ionic-angular'; import {StatusBar} from '@ionic-native/status-bar'; import {SplashScreen} from '@ionic-native/splash-screen'; import {InvitesPage} from "../pages/invites/invites"; import {RewardsPage} from "../pages/rewards/rewards"; import {ConnectionsPage} from "../pages/connections/connections"; import {MessagesPage} from "../pages/messages/messages"; import {ResourcesPage} from "../pages/resources/resources"; import {SignoutPage} from "../pages/signout/signout"; import {DashboardPage} from "../pages/dashboard/dashboard"; import {AccountPage} from "../pages/account/account"; import {HomePage} from "../pages/home/home"; import {TriviaPage} from "../pages/trivia/trivia"; import {Events} from "ionic-angular/util/events"; @Component({ templateUrl: 'app.html' }) export class MyApp { @ViewChild(Nav) nav: NavController; // make HelloIonicPage the root (or first) page public rootPage: any; //if logged in, go to dashboard. public pages: Array<{title: string, component: any}>; public user: any; public routeHistory: Array; constructor(public platform: Platform, public menu: MenuController, public statusBar: StatusBar, public splashScreen: SplashScreen, private _app: App, private _ionicApp: IonicApp, private _menu: MenuController, protected injector: Injector, public _events: Events) { this.initializeApp(); // set our app's pages this.pages = [ {title: 'My Account', component: AccountPage}, {title: 'Dashboard', component: DashboardPage}, {title: 'Invites', component: InvitesPage}, {title: 'Rewards', component: RewardsPage}, {title: 'Connections', component: ConnectionsPage}, {title: 'Messages', component: MessagesPage}, {title: 'Resources', component: ResourcesPage}, {title: 'Trivia', component: TriviaPage}, {title: 'Sign Out', component: SignoutPage} ]; this.routeHistory = []; this.user = {firstName: ''}; } initializeApp() { this.platform.ready().then(() => { this._setupBrowserBackButtonBehavior(); let self = this; if (sessionStorage.getItem('user')) { this.user = JSON.parse(sessionStorage.getItem('user')); self.rootPage = TriviaPage; } else { self.rootPage = HomePage; } this.routeHistory.push(self.rootPage); // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. this.statusBar.styleDefault(); this.splashScreen.hide(); }); } openPage(page) { // close the menu when clicking a link from the menu this.menu.close(); // navigate to the new page if it is not the current page this.nav.setRoot(page.component); //store route history this.routeHistory.push(page.component); } private _setupBrowserBackButtonBehavior() { // Register browser back button action(s) window.onpopstate = (evt) => { // Close menu if open if (this._menu.isOpen()) { this._menu.close(); return; } // Close any active modals or overlays let activePortal = this._ionicApp._loadingPortal.getActive() || this._ionicApp._modalPortal.getActive() || this._ionicApp._toastPortal.getActive() || this._ionicApp._overlayPortal.getActive(); if (activePortal) { activePortal.dismiss(); return; } if (this.routeHistory.length > 1) { this.routeHistory.pop(); this.nav.setRoot(this.routeHistory[this.routeHistory.length - 1]); } }; // Fake browser history on each view enter this._app.viewDidEnter.subscribe((app) => { if (this.routeHistory.length > 1) { history.pushState(null, null, ""); } }); } } 

    Я нашел самый простой способ , просто добавьте следующий код в app.component :

     this.platform.registerBackButtonAction((event) => { let activePortal = this.ionicApp._loadingPortal.getActive() || this.ionicApp._modalPortal.getActive() || this.ionicApp._toastPortal.getActive() || this.ionicApp._overlayPortal.getActive(); if(activePortal && activePortal.index === 0) { /* closes modal */ activePortal.dismiss(); } else { if(this.nav.getActive().name == 'Homepage') { // your homepage this.platform.exitApp(); } else { if(this.nav.canGoBack()) this.nav.pop(); this.nav.setRoot(Homepage); } } },101); 

    Это оно! Не нужно добавлять дополнительный код на каждую страницу!

    Решение для лучшей практики после длительного поиска.

    он работает на 100% и проверяет его на реальном устройстве

      this.Platform.registerBackButtonAction(() => { // try to dismiss any popup or modal console.log("Back button action called"); let activePortal = this.ionicApp._loadingPortal.getActive() || this.ionicApp._modalPortal.getActive() || this.ionicApp._toastPortal.getActive() || this.ionicApp._overlayPortal.getActive(); if (activePortal) { // ready = false; activePortal.dismiss(); activePortal.onDidDismiss(() => { }); console.log("handled with portal"); return; } // try to close the menue if(this.MenuController.isOpen()){ this.closeMenu(); return; } else if(this.nav.canGoBack()){ this.nav.pop(); return; }else{ let activePage = this.nav.getActive().instance; let whitelistPages = [LoginPage, HomePage]; // if current page is not in whitelistPage // then back to home or login page first if (whitelistPages.indexOf(activePage.constructor) < 0) { this.nav.setRoot(this.userLoggedIn ? HomePage : LoginPage); return; }else if(whitelistPages.indexOf(activePage.constructor) > 0){ this.AppUtilities.showConfirm("Exit","Are you want to exist the app ? ").subscribe( ()=>{ this.Platform.exitApp(); }, ()=>{} ) }else{ console.error('cannot handel back button') } } }); 

    У меня есть небольшой подход к сравнению с @amr abdulaziz. Я использую setTimeout для управления или возврата. Надеюсь, это даст другой вариант для реализации кнопки «Назад».

      initBackButtonBehaviour() { this.platform.registerBackButtonAction(() => { console.log("Back button pressed"); if (this.readyToExit) { this.platform.exitApp(); return; } let activePortal = this.ionicApp._loadingPortal.getActive() || this.ionicApp._modalPortal.getActive() || this.ionicApp._toastPortal.getActive() || this.ionicApp._overlayPortal.getActive(); if (activePortal) { activePortal.dismiss(); activePortal.onDidDismiss(() => { }); return; // stop any further action after closing any pop up modal or overlay } if (this.menuCtrl.isOpen()) { this.menuCtrl.close(); return; // stop any further action after menu closed } else if (this.nav.canGoBack()) { this.nav.pop(); return; // stop any further action after navigation pop } else { let activePage = this.nav.getActive().instance; let whiteListPages = [HomePage]; // if current page is not in whitelistPage // then back to home or login page first if (whiteListPages.indexOf(activePage.constructor) < 0) { this.nav.setRoot(HomePage); return; } else if (whiteListPages.indexOf(activePage.constructor) >= 0) { this.utils.showToast('Press back button again to exit', 1500); this.readyToExit = true; setTimeout(() => { this.readyToExit = false; }, 1500); } else { console.error('cannot handle back button'); } } }, 101); 

    Я исследовал много вещей для обратной кнопки. Наконец, я нашел хорошее решение для ионной последней версии 3.xx

     //Check Hardware Back Button Double Tap to Exit And Close Modal On Hardware Back let lastTimeBackPress = 0; let timePeriodToExit = 2000; this.platform.registerBackButtonAction(() => { let activePortal = this.ionicApp._loadingPortal.getActive() || // Close If Any Loader Active this.ionicApp._modalPortal.getActive() || // Close If Any Modal Active this.ionicApp._overlayPortal.getActive(); // Close If Any Overlay Active if (activePortal) { activePortal.dismiss(); } else if(this.nav.canGoBack()){ this.nav.pop(); }else{ //Double check to exit app if (new Date().getTime() - lastTimeBackPress < timePeriodToExit) { this.platform.exitApp(); //Exit from app } else { this.toast.create("Press back button again to exit"); lastTimeBackPress = new Date().getTime(); } } }); 

    В Ionic 3 Lazy Loading, я никогда не испытывал потребности в обратном обращении браузера, где, как и для platform.is (‘cordova’), я создал следующий метод, который обрабатывает все обратные сценарии:

     // If a view controller is loaded. Just dismiss it. let nav = this.app.getActiveNav(); let activePortal = this._ionicApp._loadingPortal.getActive() || this._ionicApp._modalPortal.getActive() || this._ionicApp._toastPortal.getActive() || this._ionicApp._overlayPortal.getActive(); if(activePortal && activePortal.index === 0) { /* closes modal */ activePortal.dismiss(); return; } // If a state is pushed: Pop it. if (this.nav.canGoBack()) { this.nav.pop(); return; } else // Else If its a tabs page: if (this.nav.getActiveChildNav()) { const tabs: Tabs = this.nav.getActiveChildNav(); const currentTab = tabs.getActiveChildNavs()[0]; // If any page is pushed inside the current tab: Pop it if(currentTab.canGoBack()) { currentTab.pop(); return; } else // If home tab is not selected then select it. if(tabs.getIndex(currentTab) !=0){ tabs.select(0); return; } } else // If a menu is open: close it. if (this.menu.isOpen()) { this.menu.close(); return; } if (this.exitApp) { this.platform.exitApp(); return; } this.exitApp = true; const toast = this.toastCtrl.create({ message: this.exitMessage || 'press again to exit', duration: 4000, position: 'bottom', cssClass: 'exit-toastr', }); toast.present(); setTimeout(() => { this.exitApp = false; }, 2000); 

    вы можете попробовать следующие функции:

     registerBackButton() { this.platform.registerBackButtonAction(() => { if (this.menu.isOpen()) { console.log("Menu is open!", "loggedInMenu"); this.menu.close(); console.log("this.menu.isOpen(): " + JSON.stringify(this.menu.isOpen())); return; } console.log("Checking for other pages"); let checkHomePage = true; let max = Globals.navCtrls.length; for (let i = 0; i < Globals.navCtrls.length; i++) { let n = Globals.navCtrls[i]; if (n) { if (n.canGoBack()) { console.log("Breaking the loop i: " + JSON.stringify(i)); let navParams = n.getActive().getNavParams(); if (navParams) { console.log("navParams exists"); let resolve = navParams.get("resolve"); if (resolve) { n.pop().then(() => resolve({})); } else { n.pop(); } } else { n.pop(); } checkHomePage = false; return; } } else console.log("n was null!"); } if (this.nav.getActive().instance instanceof TabsPage && !this.nav.canGoBack()) { let popPageVal = this.backbuttonService.popPage(); console.log("popPageVal: " + JSON.stringify(popPageVal)); if (popPageVal >= 0) { console.log("Switching the tab to: ", popPageVal); this.switchTab(popPageVal); } else { console.log("Last page is HomePage"); if (this.alert) { this.alert.dismiss(); this.alert = null; } else { this.showAlert(); } } } else { console.log("Last page is not HomePage"); if (this.nav.canGoBack()) { console.log("We can go back!"); this.nav.pop(); } } }); } showAlert() { this.alert = this.alertController.create({ title: "Exit?", message: "Are you sure you want to exit?", buttons: [ { text: "Cancel", role: "cancel", handler: () => { this.alert = null; } }, { text: "Exit", handler: () => { this.platform.exitApp(); } } ] }); this.alert.present(); } switchTab(tabIndex) { if (Globals.tabs && tabIndex >= 0) { console.log("Switch condition met"); Globals.tabIndex = tabIndex; Globals.tabs.select(tabIndex); Globals.tabs.selectedIndex = tabIndex; } } 

    Надеюсь, что он с тобой работает.

    Давайте будем гением компьютера.