Quantumleap
899 words
4 minutes
SwiftUIでModalWindowをカスタマイズする話

ModalWindow#

ModalWindow とは通称モーダルと言われ、メインのウィンドウとは別に画面にホバーしてくるウィンドウのこと。

どういうものなのかは見ていただいたほうが早いので GIF 動画を載せておきます。

SwiftUI での二つの実装方法#

SwiftUI のデフォルトではsheetfullScreenCoverが使えます。このうち、fullScreenCoverは iOS14 以降でないと使えないのでそれだけ気をつけてください。

Sheet#

struct ContentView: View {
    @State var isPresented: Bool = false

    var body: some View {
        Button(action: { isPresented.toggle() }, label: { Text("Open") })
            .sheet(isPresented: $isPresented) {
                Text("Hello, World")
            }
    }
}

FullScreenCover#

struct ContentView: View {
    @State var isPresented: Bool = false

    var body: some View {
        Button(action: { isPresented.toggle() }, label: { Text("Open") })
            .fullScreenCover(isPresented: $isPresented) {
                Text("Hello, World")
            }
    }
}

ModalWindow のアニメーションには次の 4 つがあります。

見た目SwiftUIUIKit
CoverVertical下から表示OKOK
CrossDissolveフェードイン-OK
FlipHorizontalフリップ-OK
PartialCurlページめくり-OK

このうち、SwiftUI でデフォルト実装されているのはCoverVerticalだけで、それ以外は利用できません。

それぞれどんなアニメーションなのかを紹介します。ただ、PartialCurlはフルスクリーンでないと利用できないので今回作成したライブラリには含めていません。

CoverVertical#

下から出現する SwiftUI デフォルトのアニメーションです。

CrossDissolve#

浮かび上がるようなアニメーションです。

FlipHorizontal#

扉が開くようなアニメーションです。

PartialCurl#

元のビューが FullScreen で表示されていないとクラッシュします。

アニメーションとは別に、表示スタイルを切り替えることができます。

automatic#

The default presentation style chosen by the system.

SwiftUI のデフォルトのsheetと同じに見えます。

none#

A presentation style that indicates no adaptations should be made.

クラッシュします。

fullScreen#

A presentation style in which the presented view covers the screen.

SwiftUI のデフォルトのfullScreenCoverと同じです。

pageSheet#

A presentation style that partially covers the underlying content.

SwiftUI のデフォルトのsheetと同じです。

formSheet#

A presentation style that displays the content centered in the screen.

自由にサイズを選べる便利なモードです。何もしなければ 540x620 で表示されます。

currentContext#

A presentation style where the content is displayed over another view controller’s content.

ModalWindow を呼び出したビューの上に表示します。

が、バグが多そうなので今回は利用していません。

custom#

A custom view presentation style that is managed by a custom presentation controller and one or more custom animator objects.

いろいろいじれそうなのですが、弄り方がわからなかったので割愛。

overFullScreen#

A view presentation style in which the presented view covers the screen.

ただのFullScreenとの違いがわからなかったので割愛。

overCurerntContext#

A presentation style where the content is displayed over another view controller’s content.

ただのcurrentContextとの違いがわからなかったので割愛。

popover#

A presentation style where the content is displayed in a popover view.

これを利用するにはいろいろ別のパラメータ設定が必要なので、ライブラリでは使えないようにしてあります。

SwiftyUI#

struct ContentView: View {
    @State var isPresented: Bool = false

    var body: some View {
        Button(action: { isPresented.toggle() }, label: { Text("Open") })
            .present(isPresented: $isPresented, transitionStyle: .coverVertical, presentationStyle: .pageSheet, isModalInPresentation: false)
    }
}

このモーダルの使い方はsheetfullScreenCoverとほとんど同じです。与えるパラメータはtransitionStyle, presentationStyle, isModalInPresentation, contentSizeの四つです。

contentSizepresentationStyleformSheetの場合でしか効かないので、設定すると強制的にformSheetになるようにしてあります。

isModalInPresentationは有効化すると画面外タッチやモーダルを下に引っ張って消すことができなくなります(iOS12 までのスタイルになります)

ユーザビリティ的には違和感があると思うので、誤タッチ等で消されたくない場合を除いてfalse(デフォルト値)で良いと思います。

記事は以上。

SwiftUIでModalWindowをカスタマイズする話
https://fuwari.vercel.app/posts/2021/08/modalwindow/
Author
tkgling
Published at
2021-08-13