ionic2/3 預處理安卓返回鍵和監聽返回鍵執行自定義操作
- 這個解決方案的預處理部分,參考了 完美處理安卓硬體返回按鈕 這篇文章,並在這個基礎上新增監聽返回鍵執行自定義操作等。
- 預處理點選返回鍵關閉鍵盤、返回上一頁、最小化 app,然後進一步處理 ActionSheet、Alert、Menu 、Select 等開啟的時候的問題。
效果預覽
安裝
-
把demo/src/core/common/back.service.ts檔案拷貝到到你的專案中。 demo 地址
-
安裝App Minimize 外掛。
ionic cordova plugin add cordova-plugin-appminimize npm install --save @ionic-native/app-minimize 複製程式碼
- 在你的專案app.module.ts新增BackService和AppMinimize供應商
import { AppMinimize } from '@ionic-native/app-minimize'; import { BackService } from ...; @NgModule({ declarations: [ ... ], imports: [ ... ], providers: [ AppMinimize, BackService ] }) export class AppModule { } 複製程式碼
BackService
一個監聽返回鍵,觸發自定義操作的服務
介面成員
state
有未執行的自定義操作返回true,無未執行的自定義操作返回false
subscribe(calback)
新增自定義返回鍵操作
Param | Type | Details |
---|---|---|
calback | function | 自定義操作的函式 |
unsubscribe()
移除一個自定義返回鍵操作
publish()
發起一個自定義返回鍵操作
clear()
清除所有所有自定義操作
使用
有些專案的第一頁不是 Tabs,而是需要登入後,才跳轉到 Tabs,所以我們需要在兩個地方寫預處理,首先給MyApp新增預處理方法,然後給Tabs新增預處理
預處理
給 MyApp 新增預處理方法
在app.html新增模板變數#myContent
<ion-nav [root]="rootPage" #myContent></ion-nav> 複製程式碼
在app.component.ts新增以下程式碼
import { Platform, Keyboard, NavController } from 'ionic-angular'; import { AppMinimize } from '@ionic-native/app-minimize'; import { BackService } from ...; export class MyApp { @ViewChild('myContent') navCtrl: NavController; constructor( private platform: Platform, private keyboard: Keyboard, private appMinimize: AppMinimize, private backService: BackService ) { platform.ready().then(() => { ... this.registerBack(); }); } // 註冊返回鍵 private registerBack() { this.platform.registerBackButtonAction(() => { if (this.keyboard.isOpen()) { // 關閉鍵盤 this.keyboard.close(); } else if (this.backService.state) { // 觸發自定義返回事件 this.backService.publish(); } else if (this.navCtrl.canGoBack()) { // 返回上一頁 this.navCtrl.pop(); } else { // 最小化app this.appMinimize.minimize(); } }, 101); } } 複製程式碼
給 Tabs 新增預處理方法
在tabs.ts新增以下程式碼
import { Component, ViewChild } from '@angular/core'; import { IonicPage, NavController, Platform, Keyboard, Tabs } from 'ionic-angular'; import { AppMinimize } from '@ionic-native/app-minimize'; import { BackService } from ...; ... export class TabsPage { ... @ViewChild(Tabs) tabs: Tabs; constructor( private navCtrl: NavController, private platform: Platform, private keyboard: Keyboard, private appMinimize: AppMinimize, private backService: BackService ) {} ionViewDidLoad() { this.registerBack(); } // 註冊返回鍵 private registerBack() { this.platform.registerBackButtonAction(() => { // 關閉鍵盤 if (this.keyboard.isOpen()) { return this.keyboard.close(); } // 觸發自定義返回事件 if (this.backService.state) { return this.backService.publish(); } const activeVC = this.navCtrl.getActive(); const page = activeVC.instance; if (!(page instanceof TabsPage)) { if (!this.navCtrl.canGoBack()) { // 最小化app return this.appMinimize.minimize(); } return this.navCtrl.pop(); } const tabs = page.tabs; const activeNav = tabs.getSelected(); if (!activeNav.canGoBack()) { // 關閉Menu if (this.menuCtrl.isOpen()) { return this.menuCtrl.close(); } // 最小化app return this.appMinimize.minimize(); } return activeNav.pop(); }, 102); } } 複製程式碼
進一步處理
通過過載 ActionSheet、Alert、Loading、Modal、Popover 等的 create 方法來監聽返回鍵。
ActionSheet
- 建立一個action-sheet.service.ts,然後新增一下程式碼
import { Injectable } from '@angular/core'; import { ActionSheetController, ActionSheet, ActionSheetOptions } from 'ionic-angular'; import { BackService } from './back.service'; @Injectable() export class ActionSheetService { constructor( private actionSheetCtrl: ActionSheetController, private backService: BackService ) {} create(options?: ActionSheetOptions): ActionSheet { const actionSheet = this.actionSheetCtrl.create(options); // onWillDismiss的時候,取消訂閱返回鍵 actionSheet.onWillDismiss(() => { this.backService.unsubscribe(); }); this.backService.subscribe(() => { // 點選返回鍵,關閉 actionSheet.dismiss(); }); return actionSheet; } } 複製程式碼
- 在你的專案app.module.ts新增ActionSheetService供應商
import { ActionSheetService } from ...; @NgModule({ declarations: [ ... ], imports: [ ... ], providers: [ ActionSheetService ] }) export class AppModule { } 複製程式碼
- 呼叫 ActionSheet 的地方,把AlertController改成ActionSheetService即可
import { ActionSheetService } from ...; export class MyPage { constructor( private alertCtrl:ActionSheetService ) {} presentActionSheet() { const actionSheet = this.alertCtrl.create({ title: 'ActionSheet', buttons: [ ... { text: 'Cancel', role: 'cancel', handler: () => { ... } } ] }); actionSheet.onDidDismiss(() => { ... }); actionSheet.present(); } 複製程式碼
Alert、Loading、Modal、Popover的實現方法跟 ActionSheet 一樣
特殊處理
使用ion-select和ion-datetime需要做特殊處理。
ion-select
新增模板引用變數並繫結事件click 事件
<ion-select [(ngModel)]="gender" #genderSelect (click)="openSelect()"> <ion-option value="f">Female</ion-option> <ion-option value="m">Male</ion-option> </ion-select> 複製程式碼
然後新增以下程式碼
import { ViewChild } from '@angular/core'; import { Select } from 'ionic-angular'; import { BackService } from ...; export class MyPage { ... @ViewChild('genderSelect') genderSelect: Select; constructor(private backService: BackService) {} ionViewDidLoad() { this.genderSelect.ionBlur.subscribe(() => { this.backService.unsubscribe(); }); } openSelect() { this.backService.subscribe(() => { this.genderSelect.close(); }); } } 複製程式碼
ion-datetime
新增模板引用變數並繫結事件click 事件
<ion-item> <ion-label>Date</ion-label> <ion-datetime [(ngModel)]="myDate" #datePicker (click)="openDatePicker()" ></ion-datetime> </ion-item> 複製程式碼
然後新增以下程式碼
import { ViewChild } from '@angular/core'; import { DateTime } from 'ionic-angular'; import { BackService } from ...; export class MyPage { ... @ViewChild('datePicker') datePicker: DateTime; constructor(private backService: BackService) {} ionViewDidLoad() { this.datePicker.ionBlur.subscribe(() => { this.backService.unsubscribe(); }); } openDatePicker() { this.backService.subscribe(() => { this.datePicker.close(); }); } } 複製程式碼