Ionic 2: 如何处理硬件返回按钮以检查应用程序退出确认

10
我遇到了一个问题,如何处理默认移动设备的后退按钮,该按钮在退出应用程序时检查确认,如果我按下后退按钮,则应调用一些处理程序来显示弹出以确认退出。 还是有一种方法可以调用registerBackButtonAction()吗?如果有,在IONIC 2中如何使用它? 请帮帮我。谢谢预先。
7个回答

26

在 app.component.ts 文件中

        @ViewChild(Nav) nav: Nav;

        constructor(private platform: Platform, private toastCtrl:   ToastController, private alertCtrl: AlertController) {
            platform.ready().then(() => {
              // Okay, so the platform is ready and our plugins are available.
              // Here you can do any higher level native things you might need

              platform.registerBackButtonAction(() => {


                //uncomment this and comment code below to to show toast and exit app
                // if (this.backButtonPressedOnceToExit) {
                //   this.platform.exitApp();
                // } else if (this.nav.canGoBack()) {
                //   this.nav.pop({});
                // } else {
                //   this.showToast();
                //   this.backButtonPressedOnceToExit = true;
                //   setTimeout(() => {

                //     this.backButtonPressedOnceToExit = false;
                //   },2000)
                // }

                if(this.nav.canGoBack()){
                  this.nav.pop();
                }else{
                  if(this.alert){ 
                    this.alert.dismiss();
                    this.alert =null;     
                  }else{
                    this.showAlert();
                   }
                }
              });
            });

          }

          showAlert() {
          this.alert = this.alertCtrl.create({
            title: 'Exit?',
            message: 'Do you want to exit the app?',
            buttons: [
              {
                text: 'Cancel',
                role: 'cancel',
                handler: () => {
                  this.alert =null;
                }
              },
              {
                text: 'Exit',
                handler: () => {
                  this.platform.exitApp();
                }
              }
            ]
          });
          alert.present();
        }

          showToast() {
            let toast = this.toastCtrl.create({
              message: 'Press Again to exit',
              duration: 2000,
              position: 'bottom'
            });

            toast.onDidDismiss(() => {
              console.log('Dismissed toast');
            });

            toast.present();
          }

这个.nav是从哪里来的? - J. Volkya
这个 this.nav 是从哪里来的? - manish kumar
@nabin:当一个页面从选项卡中的某个页面内部推出时,这种解决方案并不总是有效的:https://stackoverflow.com/questions/46757910/handling-android-back-button-in-ionic-3-with-tabs - Ari
@Ari 我没有尝试过,但是 https://dev59.com/cFgR5IYBdhLWcg3wZcm1#41373775 应该会有所帮助。 - nabin
this.alert.present(); - Tzvi Gregory Kaidanov
显示剩余5条评论

16

最新版的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
请问您能否解释一下 this.nav 是什么,以及如何在 app.component.ts 中使用 NavController? - Tejas Jain
1
当一个页面从选项卡中的某个页面内部推出时,此解决方案并不总是有效:https://stackoverflow.com/questions/46757910/handling-android-back-button-in-ionic-3-with-tabs - Ari
谢谢你的回答。我有一个场景,其中侧边菜单也是预设的,因为当我使用侧边菜单从主页(选项卡页面)转到其他页面时,this.nav.getActive(); 仅显示子页面,而不是显示主页作为活动页面。你有什么想法可以在第二个页面上弹出而不是显示toast? - Mohan Gopi

4

平台API有一个名为registerBackButtonAction的处理程序。

你可以像这样做:

在 app.component.ts 中:

    constructor(platform: Platform){
     platform.ready().then(()=>{
       platform.registerBackButtonAction(()=>this.myHandlerFunction());
})


  myHandlerFunction(){
    //create alert
     }

非常感谢你,Suraj。它对我有效。对我来说就像魔法一样。 - Tushar Rmesh Saindane
代码中唯一的更改是 this.myHandlerFunction()ready() 是函数 - Tushar Rmesh Saindane
如何关闭应用程序 - Ankush Thakur

4
这是我的可运行代码。谢谢大家的支持。
constructor(platform: Platform,public alertCtrl: AlertController,public toastCtrl:ToastController) {
    platform.ready().then(()=>{
       platform.registerBackButtonAction(()=>this.myHandlerFunction());
       StatusBar.styleDefault();
      Splashscreen.hide();
})
  }

    myHandlerFunction(){
     let toast = this.toastCtrl.create({
      message: "Press Again to Confirm Exit",
      duration: 3000
    });
    toast.present(); 
     }

1

有些项目中,后退按钮不仅仅是关闭推送页面,特别是对于有多个选项卡页面的项目。

有时候一个页面被推到了选项卡页面的navCtrl中,而不是根页面。所以我们必须检查所有这些页面。

此外,如果没有打开页面或菜单,我们应该循环浏览最近使用的选项卡(类似于Instagram应用程序),并返回到上一个选项卡。此外,我们不应该多次返回每个选项卡(类似于Instagram)

我受到这里的答案的启发,并创建了一个全面的方法来处理所有必要的功能:

  • 侧边菜单:如果它已经打开,则关闭侧边菜单
  • 推送页面:关闭可能已经推送到任何选项卡页面的导航控制器上的任何页面
  • 在选项卡之间切换:如果菜单已关闭,并且没有推送页面,则应使用堆栈将用户带回先前最近使用的选项卡。
  • 显示警报:如果没有先前最近使用的选项卡,则应显示警报框询问用户是否要退出。

详细信息请查看博客文章

演示代码可从我的Github下载。


1

我通过大量的研究成功创建了这个函数。希望它能够帮助到你。

    // I am using this.isExitAlertOpen just to make sure that the alert does not open if already open.

    handleBackButton() {
    this.platform.registerBackButtonAction(() => {
        // const activePortal =
        // this.ionicApp._modalPortal.getActive() ||
        // this.ionicApp._loadingPortal.getActive() ||
        // this.ionicApp._toastPortal.getActive() ||
        // this.ionicApp._overlayPortal.getActive();

        // console.warn('ACTIVE PORTALS', activePortal);

        const activeModal = this.ionicApp._modalPortal.getActive();
        console.warn('MODAL', activeModal);
activePortal可以用于查找相关的活动门户,包括警报、加载器、模态框等。如果您想使用后退按钮处理所有内容或其中一些内容,请根据您的使用情况取消注释。
在我的情况下,我只想检查模态框是否处于活动状态,因此只检查了模态框。
        //  if (activePortal) {
        //    activePortal.dismiss();
        //  }

        if (activeModal) {
            activeModal.dismiss();
        } else if (this.nav.canGoBack()) {
            this.nav.pop();
        } else {
            if (this.isExitAlertOpen) return;
            this.isExitAlertOpen = true;
            this.showExitAlert();
        }
    });
}

showExitAlert() {
    this.alertCtrl.create({
        title: 'Exit',
        message: 'Are you sure you want to exit the app?',
        enableBackdropDismiss: false,
        buttons: [
            {
                text: 'Yes',
                handler: () => {
                    this.isExitAlertOpen = false;
                    this.platform.exitApp();
                }
            }, {
                text: 'Cancel',
                role: 'cancel',
                handler: () => {
                    this.isExitAlertOpen = false;
                }
            }
        ]
    }).present();
}

1

Html:

<button (click)="exitApp()">Close application<button>

TypeScript:
import {Platform} from 'ionic-angular';

@Page({ /*...*/ })
export MyPage {
 constructor(platform: Platform) {
  this.platform = platform;
 }
 exitApp(){
  this.platform.exitApp();
 }
}

我认为这不是 OP 所询问的内容。问题是关于硬件返回按钮的处理程序。 - Suraj Rao
感谢Ramandeep Kaur的帮助,但我想要移动硬件返回按钮。 - Tushar Rmesh Saindane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接