ionic2/3 预处理安卓返回键和监听返回键执行自定义操作

概述

  1. 这个解决方案的预处理部分,参考了完美处理安卓硬件返回按钮这篇文章,并在这个基础上添加监听返回键执行自定义操作等。
  2. 预处理点击返回键关闭键盘、返回上一页、最小化 app,然后进一步处理 ActionSheet、Alert、Menu 、Select 等打开的时候的问题。

效果预览

安装

  1. demo/src/core/common/back.service.ts 文件拷贝到到你的项目中。 demo 地址

  2. 安装 App Minimize 插件。

ionic cordova plugin add cordova-plugin-appminimize

npm install --save @ionic-native/app-minimize
复制代码
  1. 在你的项目 app.module.ts 添加 BackServiceAppMinimize 供应商

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

  1. 创建一个 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;
  }
}
复制代码
  1. 在你的项目 app.module.ts 添加 ActionSheetService 供应商

import { ActionSheetService } from ...;

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [
    ActionSheetService
  ]
})
export class AppModule { }
复制代码
  1. 调用 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-selection-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();
    });
  }
}
复制代码

猜你喜欢

转载自juejin.im/post/5c4963af6fb9a049b5072b1b