Ionic4では画面遷移の実装が変更された影響か、Ionic3のような画面遷移アニメーションの変更ができなくなってしまった。この問題に対する暫定的な対処方法を説明する。
なお、Ionic 4.1.2 + Angularの構成で、画面遷移に<ion-router-outlet>
を主に利用している前提とする。
Ionicにおけるアニメーションの種類
Ionicでは、画面遷移時にアニメーション効果が発生する。このアニメーション効果にはMaterial Design風の効果とiOS風の効果の2種類があり、さらに、前進用と後退用のアニメーションが用意されている。
animation | direction | |
---|---|---|
'forward' | 'back' | |
'md' | ![]() |
![]() |
'ios' | ![]() |
![]() |
Ionic3の場合は、この4パターンのアニメーションをNavController
のメソッドから制御することができた。
※オプションを省略した場合は、プラットフォームに対応してanimation
が適用される。
animation | direction | |
---|---|---|
'forward' | 'back' | |
'md' | navController.push(NextComponet, {}, { animation: 'md', direction: 'forward' }) | navController.push(NextComponent, {}, { animation: 'md', direction: 'back' }) |
'ios' | navController.push(NextComponet, {}, { animation: 'ios', direction: 'forward' }) | navController.push(NextComponent, {}, { animation: 'ios', direction: 'back' }) |
Ionic4での問題
しかし、Ionic4のNavController
ではanimation
を指定するオプションが削除され、forward
とback
の区別しかつけられなくなってしまった。
animation | direction | |
---|---|---|
'forward' | 'back' | |
N/A | navController.navigateForward('nextPath', {}, { direction: 'forward' }) | navController.navigateForward('nextPath', {}, { direction: 'back' }) |
2019年5月現在、ドキュメントで説明されている限りは、遷移ごとにanimation
を切り替える方法は提供されていない。このため、iOSテーマでは常に横方向、MDテーマでは常に上下のアニメーションが強制されることになる。
デザイン上は使い分けたい
この仕様は、アニメーションを使って画面間の関係を表現したいときに単純に不便だ。UIデザイン的には、左右のアニメーションと上下のアニメーションは明確に意味が異なっているし、プラットフォームごとにどちらかへ統一するべき挙動であるとも思えない。
参考:アプリに最適なアニメーション遷移とスピードを考えてみよう!
暫定的な解決策
プラットフォーム/テーマに関係なく、Ionic3のように都度画面遷移の方向を変える方法がないか色々と試行錯誤した方法を以下へ記載する。
ただし、ドキュメントに記載がなかったり内部プロパティを使っているものは、今後の仕様変更で削除される可能性があることにも注意したい。
<ion-router-outlet>
にmode
属性を指定する
今のところドキュメントに記載されていないが、<ion-router-outlet mode="ios">
のようにmode
属性を指定すると、画面遷移のデフォルトの挙動をプラットフォームから独立して変更させることができる。
つまり、アプリ全体を通じて左右アニメーションが多い場合はmode="ios"
、上下アニメーションが多い場合はmode="md"
を指定すると都合が良くなる。
<ion-router-outlet>
のmode
属性を動的に変化させる
さらに、このmode
属性を動的に変化させた場合、そのとき付いている値に応じてアニメーションの種類も変化する。
@Components({
selector: 'app-route',
template: '<ion-app><ion-router-outlet [attr.mode]="mode"></ion-router-outlet></ion-app>'
})
export class AppComponent {
public mode: string = 'ios';
constructor(...){...}
}
@Components({
selector: 'child-component',
template: `
<ion-button (click)="navForward('md')">MD Mode</ion-button>
<ion-button (click)="navForward('ios')">iOS Mode</ion-button>
`
})
export class ChildComponent {
constructor(
private navCtrl: NavController,
@Optional() @Host() @SkipSelf() private app: AppComponent,
){...}
public navForward(mode: string): void {
this.app.mode = mode;
this.navCtrl.navigateForward('next-page');
}
}
なぜmode
属性が効いているのか
実装を見ると、modeプロパティが画面遷移を実行するときのパラメータの一部になっている。
しかし、@internal
コメントもあるため将来的に削除される可能性が否定できない。
<ion-nav>
のメソッドオプションを使う
Ionic4ではルーティングの仕様が変わり、推奨では<ion-router-outlet>
でのルーティングが推奨されている。
一方で、Ionic3にもあった<ion-nav>
での画面遷移も引き続き残されている。
(ただし、Ionic3と同じ仕様ではない。)
これを使うことで、遷移の度にmode
を指定することもできる。
とはいえ、Angular Routerでの実装に慣れているとかなり使いにくい。
完全な解決策は見つからず…
結局、完全・安全な解決策は見つかっていない。もし良い方法が見つかった場合には更新したい。