概要
React Native NavigationのshowModalのAndroid側のアニメーションだけ変えたいが、型定義ファイルにないけど実装はされているので無理やり呼ぶ方法を紹介。
ReactNativeやTypeScriptについてなどの基本的な説明は省略しています。わかる人だけ呼んでください。
React Native Navigationについて
React Navigationなどに似たReact Nativeに置けるサードパーティ製画面遷移ライブラリ。
特徴的なのは画面遷移時にネイティブのメソッドを呼ぶので、JavaScriptのViewだけを用いたライブラリと違ってOSの標準に準拠したアニメーションができること。iOS/Android対応。
React Native Navigationの画面遷移アニメーションについて
React Native NavigationのshowModal()などを呼ぶと、画面遷移アニメーションがデフォルトで下から上にスライドするアニメーションになる
OS | push | modal |
---|---|---|
ios | ||
android | ! |
動かしたければ → https://github.com/natsuki-yamanaka/TestReactNativeNavigation
問題点
iOSではいいがAndroidでは違和感のある動き
自分のプロジェクトではデフォルトの画面遷移アニメーションにしたい意向だったので修正したい。
対応策1
Androidではpush,iOSではshowModalを使う
問題点
- 戻る為のメソッドが違う
- pushの時は this.props.navigator.pop
- showModalの時は this.props.navigator.dismissModal
- 違うメソッドでは戻れないので、複雑な画面遷移の際に制御が複雑化しそう
対応策2
animationTypeを変える
React Native NavigationのanimationTypeについて
ここがこの記事の本題
React Native Navigationの画面遷移メソッド(push, pop, showModal, dismissModal, resetTo, popToRootなど)では、
this.props.navigator.push({
screen: 'Screen1',
animationType: 'fade',
});
のように、animationTypeを指定できる(公式ドキュメントを参照)
使えるanimationTypeはメソッド毎に別。
method | 使えるanimationType |
---|---|
push | fade / slide-horizontal(androidのみ) |
pop | fade / slide-horizontal(androidのみ) |
showModal | none / slide-up |
dismissModal | none / slide-down |
animationTypeを引数に与えない場合はdefaultのアニメーションになりそうですが、実際にはundefinedの場合Androidのpushはfadeでもslide-horizontalでもないアニメーションになります。
animationType毎の挙動
push/modal | animationType | ios | android |
---|---|---|---|
push | 指定なし | ||
push | fade | ||
push | slide-holizontal | ||
modal | 指定なし | ||
modal | none | ||
modal | slide-up |
push/showModalに渡すanimationTypeはあくまで遷移時のanimationTypeしか指定しません。
画面が消える時のanimationを指定したい場合はpop/dismissModalにてanimationTypeを指定することができます。
公式Githubの app/src/main/java/com/reactnativenavigation/screens/ScreenAnimator.java あたりをみるとAndroidのデフォルトはObjectAnimatorのtranslationYアニメーションを行うらしい…
今回やりたかったこと
showModalの時のアニメーションがnoneかslide-upしかない
Androidの場合はshowModalでもpushのようなアニメーションはできない…?
実はこれ以外にも実装されている
showModalのanimationTypeを判別してアニメーションを行う公式GithubのソースはModalAnimationFactory.javaで、下記のようになっている
switch (params.animationType) {
case "fade":
return R.style.ModalFadeAnimation;
case "slide-horizontal":
return R.style.ModalSlideHorizontal;
case "screen":
return R.style.ModalScreenAnimations;
default:
return R.style.ModalDefaultAnimations;
}
fade, slide-horizontal, screen などがあります…
仮にAndroidのshowModalでも
- デフォルトの下から出てくるアニメーション -
animationType: screen
- 横スライドのアニメーション -
animationType: slide-horizontal
- フェードインアニメーション -
animationType: fade
を指定するとちゃんと動きます。
Javascriptなら単純にanimationType指定でいいんですが、TypeScriptの場合型定義ファイルに slide-up
と none
しか定義がないので、Object.assignなどで無理やり引数に入れるとしっかりアニメーションが変わります。
const param = {
screen: 'Screen2',
navigatorButtons: { leftButtons: [{ id: 'cancel' }] },
} as ModalScreen;
this.props.navigator.showModal(
Object.assign(param, { animationType: 'screen' }),
);
animationType: screenを指定した結果
Android | iOS |
---|---|
Androidはデフォルトのpushと同じ、iOSはデフォルトのshowModalのアニメーションになりました。
dismissのanimationType指定してないと違和感ありますが…
以上
型定義になくてもソース読むと実装されてることもあるらしい