3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SwiftUI - 上下左右から出てくるハーフモーダルの実装

Last updated at Posted at 2021-05-23

SwiftUIでも上から下に向かうハーフモーダルの実装がなかったので、以下で実装
備忘録として残します。

image.png

使い方

SideMenuを呼び出して利用

機能概要

・表示のアニメーション
・ハーフモーダル表示中は後ろのViewの色のトーンを落とす
・後ろのViewタップ時は閉じる

実装

//ContentView.swift
import SwiftUI

struct ContentView: View {
    @State private var isOpen:Bool = false
    var body: some View {
        ZStack() {
            Button(action: {
                isOpen.toggle()
            }) {
                Text("OpenSideMenu")
                    .frame(width: 200, height: 50, alignment: .center)
                    .background(Color.black)
                    .foregroundColor(.white)
                    .cornerRadius(5.0)
            }
            
            SideMenu(view: MenuView(), width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height/2, menuType: .fromTop,isOpen: $isOpen)
        }.background(Color.green)
        .ignoresSafeArea(.all)
    }
}
//MenuView.swift
import SwiftUI

struct MenuView: View {
    var body: some View {
        VStack() {
            Text("ハーフモーダル")
                .font(.title)
                .bold()
            Image("myImg")
                .resizable()
                .clipShape(Circle())
                .overlay(
                    Circle().stroke(Color.white, lineWidth: 2))
                .frame(width: 50, height: 50, alignment: .leading)
        }
    }
}
//SideMenu.swift
import SwiftUI

//サイドメニュー
struct SideMenu<Content: View>: View {
    enum menutype {
        case fromLeft
        case fromRight
        case fromTop
        case fromBottom
    }

    let view: Content   //表示させるViewを指定
    let width: CGFloat  //メニューの幅を指定
    let height:CGFloat  //メニューの高さを指定
    let menuType: menutype //type指定(.fromLeft, .fromRight, .fromTop)
    @Binding var isOpen: Bool //BtnのBoolを引数とする
    
    var body: some View {
        ZStack {
            GeometryReader { _ in
                EmptyView()
            }
            .background(Color.gray.opacity(0.3))
            .opacity(self.isOpen ? 1.0 : 0.0)
            .animation(Animation.easeIn.delay(0.25))
            .onTapGesture {
                self.isOpen.toggle()
            }
            let displyView = view
                .frame(width: self.width, height: self.height)
                .background(Color.white)
                .animation(.default)

            switch self.menuType {
            case .fromLeft:
                HStack() {
                    displyView
                        .offset(x: self.isOpen ? 0 : -self.width)
                    Spacer()
                }
            case .fromRight:
                HStack() {
                    Spacer()
                    displyView
                        .offset(x: self.isOpen ? 0 : +self.width)
                }
            case .fromTop:
                VStack() {
                    displyView
                        .offset(y: self.isOpen ? 0 : -self.height)
                    Spacer()
                }
            case .fromBottom:
                VStack() {
                    Spacer()
                    displyView
                        .offset(y: self.isOpen ? 0 : +self.height)
                }
            }
        }.ignoresSafeArea(.all)
    }
}


3
5
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
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?