【问题标题】:How to handle back button on Ionic 2如何处理 Ionic 2 上的后退按钮
【发布时间】:2017-05-13 10:17:35
【问题描述】:

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

我希望能够根据向用户显示的页面知道该做什么。

我没有找到这个问题的好答案,但过了一段时间我自己想出了一个办法。我会和大家分享。

谢谢

【问题讨论】:

  • 为什么下面这个问题的答案这么难,又不想实施? :( 最简单、最简单的方法是什么?
  • @BiswasKhayargoli 这些如何复杂化?

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


【解决方案1】:

我是这样做的:

在每个页面组件中,我创建了一个名为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 方法中定义)。

【讨论】:

  • 让 nav = app.getActiveNav(); **这是什么应用程序**
  • 它是App组件的一个实例,从ionic-angular导入
  • 我在我的项目中使用选项卡和侧边菜单上面的答案工作正常,除了侧边菜单部分当我转到页面表单侧边菜单时我无法导航到后面我将组件名称作为主页即使当我从侧面菜单转到某个页面时我在其他页面中,我也没有看到选项卡,这是否会导致错误任何帮助如何导航到主页(tabspage)
【解决方案2】:

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

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

当用户按下原生平台的后退按钮时触发后退按钮事件,也称为“硬件”后退按钮。此事件仅在 Android 和 Windows 平台上运行的 Cordova 应用程序中使用。此事件不会在 iOS 上触发,因为 iOS 没有像 Android 或 Windows 设备那样带有硬件后退按钮。

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

参数:

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

返回:Function:一个函数,在调用时将取消注册后退按钮操作。

【讨论】:

    【解决方案3】:

    如果我们只是设置根页面,我就能做到这一点......

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          我使用此处和其他来源的答案来完成我所需要的。 我注意到,当您构建生产应用程序(--prod)时,这种方法不起作用,因为 JS 丑化和简化:

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

          因此,我在“if”语句中使用了 next:

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

          【讨论】:

          • 您如何知道当前是否打开了活动模式或警报?
          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

            与@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】:

              我为后退按钮手柄研究了很多东西最后我找到了一个适用于 ionic 最新版本 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】:

                在 Ionic 3 延迟加载中,我从不觉得需要处理浏览器的后退行为,而对于 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】:

                  你可以试试这个功能:

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

                  我希望它对你有用。

                  【讨论】:

                    【解决方案12】:

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

                    这里是关于navigating lifecycle的官方文档

                    【讨论】:

                      猜你喜欢
                      • 2017-06-20
                      • 2020-01-24
                      • 2016-08-20
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-10-26
                      • 2019-01-13
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多