如何处理Ionic 2上的后退按钮

时间:2016-12-29 05:44:54

标签: ionic2 back-button back-button-control

如何处理Ionic 2上的后退按钮操作?

我希望能够知道该怎么做,具体取决于向用户显示的页面。

我没有找到这个问题的好答案,但过了一段时间我发现自己有办法做到这一点。我要和大家分享一下。

由于

12 个答案:

答案 0 :(得分:29)

以下是我的表现:

在每个Page组件中,我创建了一个名为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并调用它,如果它不存在,只需转到主/第一个选项卡。

如果他们不需要为每个页面执行自定义操作,可以简化这一过程。你可以弹出或退出应用程序。

我是这样做的,因为我需要检查模态是否在此特定页面上打开。

代码:

  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方法中所定义)。

答案 1 :(得分:7)

  

Ionic最新版本3.xx app.component.ts文件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({});
    }
  });

});

}

答案 2 :(得分:6)

我使用了来自这里和其他来源的答案来完成我需要的东西。 我注意到当你构建生产应用程序(--prod)时,由于JS的简化和简化,这种方法不起作用:

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

因此,我在&#34;中使用了下一个&#34; if&#34;语句:

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
    }
  });
});

答案 3 :(得分:3)

根据here的Ionic 2 RC.4文档:

您可以使用registerBackButtonAction(callback, priority) API的Platform方法在后退按钮上注册操作。

当用户按下本机平台的后退按钮(也称为“硬件”后退按钮)时,将触发后退按钮事件。此事件仅在Android和Windows平台上运行的Cordova应用程序中使用。此事件不会在iOS上触发,因为iOS没有与Android或Windows设备相同的硬​​件后退按钮。

注册硬件后退按钮操作并设置优先级允许应用程序控制在按下硬件后退按钮时应调用的操作。此方法决定哪个已注册的后退按钮操作具有最高优先级,应该被调用。

参数:

  • 回调:按下后退按钮时要调用的函数,如果此注册操作具有最高优先级。
  • 优先级:用于设置此操作的优先级的数字。只执行最高优先级。默认为0

返回:功能:一个函数,当被调用时,将取消注册后退按钮操作。

答案 4 :(得分:1)

实际上,ionViewWillLeave在我的情况下效果更好。

enter image description here

以下是有关navigating lifecycle的官方文档

答案 5 :(得分: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<any>;

  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, "");
      }

    });

  }
}

答案 6 :(得分:0)

  

我找到了最简单的方式,只需在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);

就是这样! 无需在每个页面上添加额外的代码!

答案 7 :(得分:0)

长时间搜索后的最佳实践解决方案。

它100%工作,并在真实设备中进行测试

&#13;
&#13;
   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')
            }


          }

        });
&#13;
&#13;
&#13;

答案 8 :(得分:0)

与@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);

答案 9 :(得分:0)

我已经为后退按钮处理研究了很多东西最后我找到了离子最新版本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();
              }
          }            
      });

答案 10 :(得分:0)

在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);

答案 11 :(得分:0)

您可以尝试使用此功能:

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;
        }
    }

我希望它能与您一起工作。