SwiftUI - 상하 좌우에서 나오는 하프 모달 구현

14501 단어 XcodeSwiftSwiftUI
SwiftUI에서도 위에서 아래로 향하는 하프 모달 구현이 없었기 때문에 아래에서 구현
비망록으로 남깁니다.



사용법



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)
    }
}


좋은 웹페이지 즐겨찾기