在 SwiftUI 中,interactiveDismissDisabled
是一个修饰符,用于控制用户是否可以通过交互手势(如下滑)来关闭弹窗,例如 sheet
或 fullScreenCover
。这个特性是从 iOS 15 开始引入的。
语法和定义 #
interactiveDismissDisabled(_:)
是一个视图修饰符,接受一个布尔值:
true
:禁用交互式关闭功能。false
(默认):允许通过手势(例如下滑)关闭弹窗。
用法场景 #
1. 防止用户意外关闭 #
如果当前 sheet
页面中涉及未经保存的数据或未完成的表单,你可以使用 interactiveDismissDisabled(true)
禁用交互式关闭手势。
2. 强制完成特定操作 #
在某些业务逻辑中,你希望用户必须通过某种明确的操作(如点击“完成”按钮)才能关闭页面,而不能通过直接下滑或手势操作来取消。
示例代码 #
示例 1:禁止通过下滑手势关闭 sheet
#
import SwiftUI
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Open Sheet") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
SheetView()
}
}
}
struct SheetView: View {
var body: some View {
VStack(spacing: 20) {
Text("Interactive Dismiss Disabled")
.font(.title)
Text("You cannot swipe down to dismiss this sheet.")
.foregroundColor(.gray)
}
.interactiveDismissDisabled(true) // 禁用下滑手势关闭
.padding()
}
}
效果: #
用户无法通过下滑退出 SheetView
,只能通过其他方式(如按钮)来关闭页面。
示例 2:条件控制交互式关闭 #
可以根据特定条件动态启用或禁用 interactiveDismissDisabled
。
import SwiftUI
struct ContentView: View {
@State private var isPresented = true
@State private var hasUnsavedChanges = true
var body: some View {
Button("Open Sheet") {
isPresented = true
}
.sheet(isPresented: $isPresented) {
SheetView(hasUnsavedChanges: $hasUnsavedChanges)
}
}
}
struct SheetView: View {
@Binding var hasUnsavedChanges: Bool
@Environment(\.dismiss) var dismiss
var body: some View {
VStack(spacing: 20) {
Text("Unsaved Changes")
.font(.title)
Toggle("Unsaved Changes?", isOn: $hasUnsavedChanges)
Button("Save & Dismiss") {
hasUnsavedChanges = false
dismiss()
}
.buttonStyle(.borderedProminent)
}
.padding()
.interactiveDismissDisabled(hasUnsavedChanges) // 仅当有未保存的更改时禁用交互式关闭
}
}
效果: #
- 只有在
hasUnsavedChanges
为true
时,用户无法下滑关闭页面。 - 当用户完成保存操作后,可以通过下滑关闭页面。
示例 3:在 fullScreenCover
中使用
#
interactiveDismissDisabled
同样适用于 fullScreenCover
,以防止用户通过边缘滑动手势关闭全屏视图。
import SwiftUI
struct ContentView: View {
@State private var showFullScreen = false
var body: some View {
Button("Show Full Screen Cover") {
showFullScreen = true
}
.fullScreenCover(isPresented: $showFullScreen) {
FullScreenView()
}
}
}
struct FullScreenView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
VStack(spacing: 20) {
Text("Full-Screen View")
.font(.title)
Text("Swipe gesture to dismiss is disabled.")
.foregroundColor(.gray)
Button("Close") {
dismiss()
}
.buttonStyle(.borderedProminent)
}
.interactiveDismissDisabled(true) // 禁用边缘滑动手势
.padding()
}
}
效果: #
- 用户无法通过边缘滑动手势关闭全屏视图,必须点击 Close 按钮 才能退出。
示例 4:显示警告确认弹窗 #
你可以在用户尝试交互式关闭页面时显示一个确认弹窗,进一步提升用户体验。
在 SwiftUI 中,可以通过 onDisappear
和 presentationMode.wrappedValue.dismiss()
结合来实现。
import SwiftUI
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Open Sheet") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
SheetView()
}
}
}
struct SheetView: View {
@Environment(\.dismiss) var dismiss
@State private var showAlert = false
@State private var hasUnsavedChanges = true
var body: some View {
VStack(spacing: 20) {
Text("Unsaved Changes")
.font(.title)
Text("Swipe to dismiss will be disabled unless changes are saved.")
.foregroundColor(.gray)
Button("Save Changes") {
hasUnsavedChanges = false
dismiss()
}
.buttonStyle(.borderedProminent)
}
.interactiveDismissDisabled(hasUnsavedChanges)
.padding()
.alert(isPresented: $showAlert) {
Alert(
title: Text("Unsaved Changes"),
message: Text("Are you sure you want to discard your changes?"),
primaryButton: .destructive(Text("Discard")) {
dismiss()
},
secondaryButton: .cancel()
)
}
}
}
交互流程: #
interactiveDismissDisabled(true)
会在用户尝试下滑关闭时禁用手势。- 当用户有未保存的更改时,他们需要选择保存或通过弹窗确认才能关闭页面。
总结 #
interactiveDismissDisabled
核心要点
#
- 基础功能:用于禁用 SwiftUI 弹窗(
sheet
、fullScreenCover
等)通过手势关闭的能力。 - 接受参数:
true
:禁用手势关闭。false
(默认):允许手势关闭。
- 响应逻辑:适合防止用户误触关闭场景,如编辑未保存的数据或强制操作完成。
适用场景 #
- iOS 15 及更高支持。
- 避免意外退出表单、编辑页面。
- 为交互式关闭增加确认操作的机会。
通过 interactiveDismissDisabled
,可以更灵活地控制页面关闭方式,加强用户行为的引导与数据保护。