web-dev-qa-db-ja.com

Ionic 2で戻るボタンを処理する方法

Ionic 2?で戻るボタンのアクションを処理するにはどうすればよいですか?

どのページがユーザーに表示されているかに応じて、何をすべきかを知りたい。

この質問に対する良い答えは見つかりませんでしたが、しばらくして、自分でそれを行う方法を見つけました。皆さんと共有します。

ありがとう

15

以下がその方法です。

すべての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.tsplatform.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メソッドで定義されているとおり)。

29

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

});

}
7
Mohamed Arshath

ここや他のソースからの回答を使用して、必要なことを達成しました。実稼働(--prod)用のアプリケーションをビルドするとき、JSがuい、単純化するため、このアプローチは機能しないことに気付きました。

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

here のIonic 2 RC.4ドキュメントによると:

Platform AP​​IのregisterBackButtonAction(callback, priority)メソッドを使用して、戻るボタンを押したときにアクションを登録できます。

ユーザーがネイティブプラットフォームの戻るボタン(「ハードウェア」の戻るボタンとも呼ばれます)を押すと、戻るボタンイベントがトリガーされます。このイベントは、AndroidおよびWindowsプラットフォームで実行されているCordovaアプリ内でのみ使用されます。 iOSにはAndroidまたはWindowsデバイスと同じ意味でハードウェアの戻るボタンが付属していないため、このイベントはiOSでは発生しません。

ハードウェアの戻るボタンのアクションを登録して優先順位を設定すると、ハードウェアの戻るボタンが押されたときに呼び出すアクションをアプリで制御できます。このメソッドは、登録された戻るボタンアクションの中で最も高い優先度を持ち、呼び出されるべきものを決定します。

パラメーター :

  • callback:この登録済みアクションの優先度が最も高い場合、戻るボタンが押されたときに呼び出される関数。
  • priority:このアクションの優先度を設定する数値。最高の優先度のみが実行されます。デフォルトは0

戻り値:Function:呼び出されたときに戻るボタンアクションの登録を解除する関数。

3
Prerak Tiwari

私の場合、実際にはionViewWillLeaveの方がうまく機能します。

enter image description here

ライフサイクルのナビゲート に関する公式ドキュメントは次のとおりです。

1
Alexey Strakh

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);
0
Arslan Ali

最も簡単な方法を見つけました。次のコードを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);

それでおしまい! すべてのページにコードを追加する必要はありません!

0
Tushar Walzade

@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);
0
Kimman wky

長い検索後のベストプラクティスソリューション。

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


          }

        });
0
Amr Ibrahim

バックボタンハンドルについて多くのことを調査しました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();
              }
          }            
      });
0
Mohamed Arshath

この機能を試すことができます:

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

私はそれがあなたと働くことを望みます。

0
Amr AbdelRahman

ルートページを設定するだけで、これを達成できました...

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
Judson Terrell