【SwiftUI】sheetの背景を透過させる方法
SwiftUIで.sheet
や.fullScreenCover
でシートを重ねた時に背景を透過させる方法を調べました。
環境
Xcode 14
やりたいこと
やりたいことはこんな風に前面にsheetを出しても背面のViewが見えるようにすることです。
はじめに
今回は、BackView
とFrontView
というものを準備しました。
BackView
コード
import SwiftUI struct BackView: View { var body: some View { VStack { Image("mr-transparent") .resizable() Text("透けて見えたら成功") .bold() } } }
プレビュー
FrontView
コード
import SwiftUI struct FrontView: View { var body: some View { ZStack { RoundedRectangle(cornerRadius: 18) .fill(.orange) .frame(width: 200, height: 100) Text("背面のViewを見たい") .bold() } } }
プレビュー
背景を透過させる
ZStackでViewを重ねる
ZStack
を使用して、Viewを重ねると前面にViewを重ねても背面のViewを確認することが出来ます。
コード
import SwiftUI struct ZStackLayeredView: View { var body: some View { ZStack { BackView() FrontView() } } }
プレビュー
sheetを出して前面のViewを透過させる
ZStackで重ねる方法だと背面のViewを確認出来ますが、今回やりたかったことはsheetで前面のViewを透過になります。
コード
import SwiftUI struct SheetLayeredView: View { var body: some View { BackView() .fullScreenCover(isPresented: .constant(true)) { FrontView() } } }
プレビュー
単純に重ねるだけだと、sheetの背景が透明になっておらず背面のViewを確認することが出来ませんでした。
.background(clear)にしてもダメ
下記のように.background(.clear)
にしてもsheetの背景には影響を与えることはできませんでした。
struct SheetLayeredView: View { var body: some View { BackView() .fullScreenCover(isPresented: .constant(true)) { FrontView() .background(.clear) } } }
sheetが透過出来ない原因
デフォルトでは全てのHostingController
の背景が不透明な為、そのViewを見つけて透過させる必要がある
解決策
UIViewRepresentable
でmakeUIView
の際にPresentationHostingController
のbackgroundColor
を透明に変更します。
struct BackgroundClearView: UIViewRepresentable { func makeUIView(context: Context) -> UIView { let view = UIView() Task { view.superview?.superview?.backgroundColor = .clear } return view } func updateUIView(_ uiView: UIView, context: Context) {} }
view.superView?.superView
でPresentationHositingController
の背景のプロパティにアクセスすることが出来ます。そのbackgroundColor
に.clear
を渡して透明にしています。
使い方
今回は先ほどのBackgroundClearView
を.background
に設定するViewのエクステンションを作成しました。
extension View { func backgroundClearSheet() -> some View { background(BackgroundClearView()) } }
完成したもの
無事にsheetの背景を透明にして、背面のViewを確認することが出来ました。
コード
import SwiftUI struct SheetLayeredView: View { var body: some View { BackView() .fullScreenCover(isPresented: .constant(true)) { FrontView() .backgroundClearSheet() } } }
プレビュー
おわりに
標準APIで変更できるようになっていない為、ゴニョゴニョしてsheetの背景色を変更する結果になりました。この記事が誰かの救いになれば嬉しいです。
もし、他に良い対応方法があれば教えていただければと思います。