はじめに
遷移元画面を透過させる方法として、 modalPresentationStyle
を overCurrentContext
にする方法がよく知られています。
let modalViewController = ModalViewController()
modalViewController.view.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.6)
modalViewController.modalPresentationStyle = .overCurrentContext
present(modalViewController, animated: false)
基本的には、 この方法で問題ないのですが、 UITabBarController
& UINavigationController
を使用している場合、 TabBar
が遷移先画面の上に来てしまいます。
TabBar
を出し続けたい場合はこのままでもいいですが、透過させたい場合は、遷移先画面が TabBar
の上に来て欲しいことの方が多いのではないでしょうか。
解決策
解決策を先に書いてしまいますが、 modalPresentationStyle
に overFullScreen
を指定することで解決できます。
let modalViewController = ModalViewController()
modalViewController.view.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.6)
// ここを overCurrentContext -> overFullScreen に変更
modalViewController.modalPresentationStyle = .overFullScreen
present(modalViewController, animated: false)
この方法で要件は満たせるのですが、実は overCurrentContext
のままでもこの問題を回避する方法があります。
UIModalPresentationStyle.overCurrentContextの仕様を追う
UIModalPresentationStyle.overCurrentContext
のドキュメントの一文に
Using this presentation style, the current view controller's content is displayed over the view controller whose definesPresentationContext property is true.
とあります。
definesPresentationContext
が true
のViewController上に表示されるようです。
definesPresentationContext
のドキュメントには、
If no view controller defines the presentation context, UIKit asks the window’s root view controller to handle the presentation.
とあり、
The default value for this property is false.
とあります。
そして最後に
Some system-provided view controllers, such as UINavigationController, change the default value to true.
となっています。
デフォルト値は false
なので基本的には、 window’s root view controller
でpresentされるようですが、 UINavigationController
は、 definesPresentationContext
が true
となるので、 UINavigationController
でpresentされるようです。(ちなみに UITabBarController
も true
)
よって overCurrentContext
を使用したまま TabBar
の上に表示するには、 UINavigationController
の definesPresentationContext
を false
にしてあげればいいわけです。
let modalViewController = ModalViewController()
modalViewController.view.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.6)
modalViewController.modalPresentationStyle = .overCurrentContext
// 下の1行を追加
navigationController?.definesPresentationContext = false
present(modalViewController, animated: false)
これにより window’s root view controller
(ここでは UITabBarController
)からpresentされるようになります。
overFullScreen
は window’s root view controller
からpresentされるようなので TabBar
の上に表示されるわけですね。
まとめ
ここまで説明してきましたが、要するに UITabBarController
でpresentしてあげれば TabBar
の上に表示させられます。
なので、 tabBarController?.present
や UIApplication.shared.keyWindow?.rootViewController?.present
でも実現できますが、拡張性や汎用性を考慮してこのような方法は極力取らない方がいいと思います。
先に書きましたが、この場合は overFullScreen
を指定してあげる方法がもっともシンプルな方法だと思います。
余談
UIPresentationController
を使用したモーダル表示の場合、 modalPresentationStyle
に custom
を指定しますが、 custom
もroot view controllerからpresentされるのでtabBarの上に表示されます。