Layout — interactiveDismissDisabled

SwiftUI 中,interactiveDismissDisabled 是一个修饰符,用于控制用户是否可以通过交互手势(如下滑)来关闭弹窗,例如 sheetfullScreenCover。这个特性是从 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) // 仅当有未保存的更改时禁用交互式关闭
    }
}

效果: #

  • 只有在 hasUnsavedChangestrue 时,用户无法下滑关闭页面。
  • 当用户完成保存操作后,可以通过下滑关闭页面。

示例 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 中,可以通过 onDisappearpresentationMode.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()
            )
        }
    }
}

交互流程: #

  1. interactiveDismissDisabled(true) 会在用户尝试下滑关闭时禁用手势。
  2. 当用户有未保存的更改时,他们需要选择保存或通过弹窗确认才能关闭页面。

总结 #

interactiveDismissDisabled 核心要点 #

  1. 基础功能:用于禁用 SwiftUI 弹窗(sheetfullScreenCover 等)通过手势关闭的能力。
  2. 接受参数
    • true:禁用手势关闭。
    • false(默认):允许手势关闭。
  3. 响应逻辑:适合防止用户误触关闭场景,如编辑未保存的数据或强制操作完成。

适用场景 #

  • iOS 15 及更高支持。
  • 避免意外退出表单、编辑页面。
  • 为交互式关闭增加确认操作的机会。

通过 interactiveDismissDisabled,可以更灵活地控制页面关闭方式,加强用户行为的引导与数据保护。

本文共 1247 字,上次修改于 Feb 9, 2025
相关标签: SwiftUI