Swift UI 해제 모달
스위프트 이후UI는 선언적입니다. 없습니다.dismiss
방법.에서는 어떻게 다음에 해제/닫기 버튼을 추가할 수 있습니까?DetailView
?
struct DetailView: View {
var body: some View {
Text("Detail")
}
}
struct ContentView : View {
var body: some View {
PresentationButton(Text("Click to show"), destination: DetailView())
}
}
@State 속성 래퍼 사용(권장)
struct ContentView: View {
@State private var showModal = false
var body: some View {
Button("Show Modal") {
self.showModal.toggle()
}.sheet(isPresented: $showModal) {
ModalView(showModal: self.$showModal)
}
}
}
struct ModalView: View {
@Binding var showModal: Bool
var body: some View {
Text("Modal view")
Button("Dismiss") {
self.showModal.toggle()
}
}
}
프레젠테이션 모드 사용
사용할 수 있습니다.presentationMode
모달 보기 및 호출의 환경 변수self.presentaionMode.wrappedValue.dismiss()
모달을 해제하는 방법:
struct ContentView: View {
@State private var showModal = false
// If you are getting the "can only present once" issue, add this here.
// Fixes the problem, but not sure why; feel free to edit/explain below.
@SwiftUI.Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
var body: some View {
Button(action: {
self.showModal = true
}) {
Text("Show modal")
}.sheet(isPresented: self.$showModal) {
ModalView()
}
}
}
struct ModalView: View {
@Environment(\.presentationMode) private var presentationMode
var body: some View {
Group {
Text("Modal view")
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Dismiss")
}
}
}
}
iOS 15+
대신에presentationMode
이제 사용할 수 있습니다.DismissAction
.
다음은 설명서의 예입니다.
struct SheetView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationView {
SheetContents()
.toolbar {
Button("Done") {
dismiss()
}
}
}
}
}
Xcode 11 Beta 5에서는 모달을 실행하는 뷰에서 @State를 사용하고 모달 뷰에 바인딩을 추가하여 모달의 가시성을 제어합니다.따라서 @Environment presentationMode 변수에 접근할 필요가 없습니다.
struct MyView : View {
@State var modalIsPresented = false
var body: some View {
Button(action: {self.modalIsPresented = true}) {
Text("Launch modal view")
}
.sheet(isPresented: $modalIsPresented, content: {
MyModalView(isPresented: self.$modalIsPresented)
})
}
}
struct MyModalView : View {
@Binding var isPresented: Bool
var body: some View {
Button(action: {self.isPresented = false}) {
Text("Close modal view")
}
}
}
다음은 제시된 보기를 무시하는 방법입니다.
struct DetailView: View {
@Binding
var dismissFlag: Bool
var body: some View {
Group {
Text("Detail")
Button(action: {
self.dismissFlag.toggle()
}) {
Text("Dismiss")
}
}
}
}
struct ContentView : View {
@State var dismissFlag = false
var body: some View {
Button(action: {
self.dismissFlag.toggle()
})
{ Text("Show") }
.presentation(!dismissFlag ? nil :
Modal(DetailView(dismissFlag: $dismissFlag)) {
print("dismissed")
})
}
}
Xcode 11 베타 7(이것은 Xcode의 빌드 11M392r에 있음)의 경우 약간 다른 것 같습니다.
@Environment(\.presentationMode) var presentation
Button(action: { self.presentation.wrappedValue.dismiss() }) { Text("Dismiss") }
Swift 5.5 및 Swift의 새로운 기능UI 3:
@Environment(\.dismiss) var dismiss
그런 다음 기능 또는 신체 코드의 어딘가에서 간단히 전화하십시오.
self.dismiss()
구현할 수 있습니다.
struct view: View {
@Environment(\.isPresented) private var isPresented
private func dismiss() {
isPresented?.value = false
}
}
자동으로 팝업 표시(인 경우)Navigation
또는 다음과 같은 경우에 기각합니다.Modal
그냥 가져가세요.presentationMode
대상 보기의 환경에서 사용할 수 있습니다.dismiss
그wrappedValue
여기서:
struct DestinationView: View {
@Environment(\.presentationMode) private var presentationMode
var body: some View {
Button("Dismiss") {
self.presentationMode.wrappedValue.dismiss()
}
}
}
데모(팝/해제)
이제 베타 5에서 이를 수행하는 꽤 깨끗한 방법이 있습니다.
import SwiftUI
struct ModalView : View {
// In Xcode 11 beta 5, 'isPresented' is deprecated use 'presentationMode' instead
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
Group {
Text("Modal view")
Button(action: { self.presentationMode.wrappedValue.dismiss() }) { Text("Dismiss") }
}
}
}
struct ContentView : View {
@State var showModal: Bool = false
var body: some View {
Group {
Button(action: { self.showModal = true }) { Text("Show modal via .sheet modifier") }
.sheet(isPresented: $showModal, onDismiss: { print("In DetailView onDismiss.") }) { ModalView() }
}
}
}
부터PresentationButton
사용하기 쉽지만 예측 특성을 훼손하는 상태를 숨깁니다.SwiftUI
액세스 가능한 상태로 구현했습니다.Binding
.
public struct BindedPresentationButton<Label, Destination>: View where Label: View, Destination: View {
/// The state of the modal presentation, either `visibile` or `off`.
private var showModal: Binding<Bool>
/// A `View` to use as the label of the button.
public var label: Label
/// A `View` to present.
public var destination: Destination
/// A closure to be invoked when the button is tapped.
public var onTrigger: (() -> Void)?
public init(
showModal: Binding<Bool>,
label: Label,
destination: Destination,
onTrigger: (() -> Void)? = nil
) {
self.showModal = showModal
self.label = label
self.destination = destination
self.onTrigger = onTrigger
}
public var body: some View {
Button(action: toggleModal) {
label
}
.presentation(
!showModal.value ? nil :
Modal(
destination, onDismiss: {
self.toggleModal()
}
)
)
}
private func toggleModal() {
showModal.value.toggle()
onTrigger?()
}
}
사용 방법은 다음과 같습니다.
struct DetailView: View {
@Binding var showModal: Bool
var body: some View {
Group {
Text("Detail")
Button(action: {
self.showModal = false
}) {
Text("Dismiss")
}
}
}
}
struct ContentView: View {
@State var showModal = false
var body: some View {
BindedPresentationButton(
showModal: $showModal,
label: Text("Show"),
destination: DetailView(showModal: $showModal)
) {
print("dismissed")
}
}
}
Xcode 11.0 베타 7에서는 이제 값이 래핑되어 다음 기능이 작동합니다.
func dismiss() {
self.presentationMode.wrappedValue.dismiss()
}
Swift의 모달 뷰UI는 나중에 사용하기 시작하기 전까지는 간단한 것 같습니다.List
또는Form
뷰. 나는 모든 가장자리 케이스를 싸고 모달 뷰의 사용을 동일하게 만드는 작은 라이브러리를 만들었습니다.NavigationView
-NavigationLink
짝.
도서관은 https://github.com/diniska/modal-view 에서 개방형으로 운영됩니다.Swift Package Manager를 사용하거나 라이브러리에 포함된 단일 파일을 복사하여 프로젝트에 포함할 수 있습니다.
코드 해결 방법은 다음과 같습니다.
struct DetailView: View {
var dismiss: () -> ()
var body: some View {
Text("Detail")
Button(action: dismiss) {
Text("Click to dismiss")
}
}
}
struct ContentView : View {
var body: some View {
ModalPresenter {
ModalLink(destination: DetailView.init(dismiss:)) {
Text("Click to show")
}
}
}
}
또한 다음과 같은 자세한 설명과 예제가 포함된 기사가 있습니다.Swift UI에서 모달 뷰를 표시하는 방법
프레젠테이션 모드를 사용하여 해제할 수 있습니다.선언하다
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
그런 다음 필요한 경우 다음과 같이 해제합니다.
self.presentationMode.wrappedValue.dismiss()
프레젠테이션 모드에서 환경 변수를 사용합니다.이 GitHub 링크는 문제를 해결하는 데 도움이 될 것입니다. https://github.com/MannaICT13/Sheet-in-SwiftUI
간단한 솔루션은 다음과 같습니다.
struct ContentView2 : View {
@Environment (\.presentationMode) var presentationMode
var body : some View {
VStack {
Text("This is ContentView2")
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text("Back")
})
}
}
}
struct ContentView: View {
@State var isShowingSheet : Bool = false
var body: some View {
Button(action: {
self.isShowingSheet.toggle()
}, label: {
Text("Click Here")
}).sheet(isPresented: $isShowingSheet, content: {
ContentView2()
})
}
}
이 작업을 수행하는 한 가지 방법은 모달 프레젠테이션 및 해제에 대한 고유한 수식어를 선언하는 것입니다.
extension View {
func showModal<T>(_ binding: Binding<Bool>, _ view: @escaping () -> T) -> some View where T: View {
let windowHeightOffset = (UIApplication.shared.windows.first?.frame.height ?? 600) * -1
return ZStack {
self
view().frame(maxWidth: .infinity, maxHeight: .infinity).edgesIgnoringSafeArea(.all).offset(x: 0, y: binding.wrappedValue ? 0 : windowHeightOffset)
}
}
}
그런 다음 뷰를 표시하고 해당 뷰를 해제하는 방법을 알려줄 뷰에 대한 한정자를 사용할 수 있습니다.팝업이나 시트 수식어처럼 말입니다.
struct ContentView: View {
@State var showModal = false
var body: some View {
Text("Show").foregroundColor(.blue).onTapGesture {
withAnimation(.easeIn(duration: 0.75)) {
self.showModal = true
}
}.showModal($showModal, {
Text("Dismiss").foregroundColor(.blue).onTapGesture {
withAnimation(.easeIn(duration: 0.75)) {
self.showModal = false
}
}
})
}
}
프레젠테이션이 위에서 전체 화면으로 표시됩니다. 측면에서 표시하려면 수식어 내부의 전환을 선행 또는 후행으로 변경하십시오.불투명도나 규모와 같은 다른 전환도 가능합니다.
Swift UI 2 코드 샘플(모바일에서도 작동)
(1과 이 되지 , (sample code는 swift 1과 연동이 되지 않습니다.) 할 수 @main
으)로 표시)
시트 사용을 위한 전체 앱 샘플:
@main
struct TestAppApp: App {
var body: some Scene {
WindowGroup {
SheetLink(text: "click me!", content: ChildView() )
.padding(.all, 100)
}
}
}
struct ChildView: View {
var body: some View {
Text("this is subView!")
}
}
하위 뷰가 기본 뷰보다 클 경우:
그리고 그 이면의 코드는:
struct SheetLink<Content> : View where Content: View {
@State var text: String
@State var displaySheet = false
@State var content: Content
var body: some View {
HStack {
Button(text, action: { self.displaySheet = true } ).buttonStyle(PlainButtonStyle()).foregroundColor(.blue)
}
.sheet(isPresented: $displaySheet) {
SheetTemplateView(isPresented: self.$displaySheet, content: content)
}
}
}
struct SheetTemplateView<Content> : View where Content: View {
@Binding var isPresented: Bool
@State var content: Content
var body: some View {
VStack{
HStack{
Button("Back!", action: { isPresented.toggle() } ).buttonStyle(PlainButtonStyle()).foregroundColor(.blue)
Spacer()
}
Spacer()
content
Spacer()
}
.padding()
}
}
SheetKit를 사용하여 모든 시트를 제거할 수 있습니다.
SheetKit().dismissAllSheets()
또는 새로운 UISheet 프레젠테이션 컨트롤러 제공
sheetKit.present(with: .bottomSheet){
Text("Hello world")
}
언급URL : https://stackoverflow.com/questions/56517400/swiftui-dismiss-modal
'programing' 카테고리의 다른 글
도커: 상위 디렉토리에서 파일 추가 (0) | 2023.08.05 |
---|---|
메인 스레드에서 메서드를 호출하시겠습니까? (0) | 2023.08.05 |
전자 메일을 보내기 위해 Send-MailMessage 명령에 자격 증명을 전달하는 방법 (0) | 2023.08.05 |
Oracle Insert via 한 테이블에 행이 없을 수 있는 여러 테이블 중에서 선택 (0) | 2023.08.05 |
'root@localhost' 사용자에 대한 액세스가 거부되었습니다(암호 사용:아니오) (0) | 2023.08.05 |