How to handle back button on Ionic 2

前端 未结 12 1546
野的像风
野的像风 2020-11-29 04:04

How can I handle the back button action on Ionic 2?

I want to be able to know what to do depending on which page is being shown to the user.

I didn\'t find a

相关标签:
12条回答
  • 2020-11-29 04:47

    I was able to accomplish this in the event that we are simply setting root pages...

    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, "");
          }
    
        });
    
      }
    }
    
    0 讨论(0)
  • 2020-11-29 04:49

    Best practice solution after long search .

    it works 100%, and tested it in real device

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

    0 讨论(0)
  • 2020-11-29 04:50

    As per Ionic 2 RC.4 documentation from here:

    You can use registerBackButtonAction(callback, priority) method of Platform API to register the action on back button press.

    The back button event is triggered when the user presses the native platform’s back button, also referred to as the “hardware” back button. This event is only used within Cordova apps running on Android and Windows platforms. This event is not fired on iOS since iOS doesn’t come with a hardware back button in the same sense an Android or Windows device does.

    Registering a hardware back button action and setting a priority allows apps to control which action should be called when the hardware back button is pressed. This method decides which of the registered back button actions has the highest priority and should be called.

    Parameters :

    • callback : Function to be called when the back button is pressed, if this registered action has the highest priority.
    • priority : Number to set the priority for this action. Only the highest priority will execute. Defaults to 0

    Returns: Function : A function that, when called, will un-register the back button action.

    0 讨论(0)
  • 2020-11-29 04:52

    I used answers from here and other sources to accomplish what I needed. I noticed that when you build the application for production (--prod) this approach doesn't work, because of JS uglifying and simplifying:

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

    Because of that, I use next in the "if" statement:

    view.instance instanceof PageOne
    

    So the final code looks like this:

    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
        }
      });
    });
    
    0 讨论(0)
  • 2020-11-29 04:53

    I have a slight different approach compare with @amr abdulaziz. Im using the setTimeout to control back or exit. Hope this would give another option for implement the back button.

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

    0 讨论(0)
  • 2020-11-29 04:54

    In Ionic 3 Lazy Loading, I never felt the need of Handling back behavior of browser where as for platform.is('cordova') I have created following method which handles all back scenarios:

    // 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);
    
    0 讨论(0)
提交回复
热议问题