LoginSignup
3
3

More than 5 years have passed since last update.

React Native NavigationのTypeScriptの型定義にない実装を呼ぶ

Posted at

概要

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 ios_push.gif ios_modal.gif
android android_push.gif !android_modal2.gif

動かしたければ → 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 指定なし ios_push.gif android_push.gif
push fade ios_push_fade.gif android_push_fade.gif
push slide-holizontal ios_push_slide_holizontal.gif android_push_horizontal.gif
modal 指定なし ios_modal.gif android_modal2.gif
modal none ios_modal_none.gif android_modal_none.gif
modal slide-up ios_modal_slide_up.gif android_modal_slide_up.gif

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-upnone しか定義がないので、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_modal_custom.gif ios_modal_custom.gif

Androidはデフォルトのpushと同じ、iOSはデフォルトのshowModalのアニメーションになりました。
dismissのanimationType指定してないと違和感ありますが…

以上

型定義になくてもソース読むと実装されてることもあるらしい

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3