我正在创建一个应用程序,其中登录/注册部分位于模式内部,如果用户未登录,则会显示该模式。
问题是,用户可以通过向下滑动模式来消除该模式...
是否可以防止这种情况?
var body: some View {
TabView(selection: $selection) {
App()
}.sheet(isPresented: self.$showSheet) { // This needs to be non-dismissible
LoginRegister()
}
}
第二个示例:
我正在使用模式询问信息。除非通过使用“保存”按钮关闭模态,否则用户不能退出该过程。用户必须在按钮起作用之前输入信息。不幸的是,可以通过向下滑动来消除模态。
是否可以防止这种情况?
答案 0 :(得分:5)
您可以尝试使用highPriorityGesture
来执行此操作。当然,蓝色矩形仅用于演示,但是您必须使用覆盖整个屏幕的视图。
struct ModalViewNoClose : View {
@Environment(\.presentationMode) var presentationMode
let gesture = DragGesture()
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(width: 300, height: 600)
.highPriorityGesture(gesture)
.overlay(
VStack{
Button("Close") {
self.presentationMode.value.dismiss()
}.accentColor(.white)
Text("Modal")
.highPriorityGesture(gesture)
TextField("as", text: .constant("sdf"))
.highPriorityGesture(gesture)
} .highPriorityGesture(gesture)
)
.border(Color.green)
}
}
答案 1 :(得分:3)
这是一个常见的问题,是一种“代码异味” ...并不是真正的代码,而是一种“设计模式异味”。
问题在于您正在使登录过程成为应用程序其余部分的一部分。
您应该真正显示LoginRegister
或App
,而不是在App
上方显示LoginRegister
。
即您应该有一些状态对象,例如userLoggedIn: Bool
或其他内容,并根据该值显示App
或LoginRegister
。
仅在同一时间不在视图层次结构中。这样,您的用户将无法关闭视图。
答案 2 :(得分:1)
从 iOS 15 开始,您可以使用 interactiveDismissDisabled
。
您只需要将其附加到工作表上:
var body: some View {
TabView(selection: $selection) {
App()
}.sheet(isPresented: self.$showSheet) {
LoginRegister()
.interactiveDismissDisabled(true)
}
}
关于你的第二个例子,你可以传递一个变量来控制何时禁用工作表:
.interactiveDismissDisabled(!isAllInformationProvided)
您可以在 documentation 中找到更多信息。
答案 3 :(得分:0)
如果您不介意使用Introspect:
import Introspect
@available(iOS 13, *)
extension View {
/// A Boolean value indicating whether the view controller enforces a modal behavior.
///
/// The default value of this property is `false`. When you set it to `true`, UIKit ignores events
/// outside the view controller's bounds and prevents the interactive dismissal of the
/// view controller while it is onscreen.
public func isModalInPresentation(_ value: Bool) -> some View {
introspectViewController {
$0.isModalInPresentation = value
}
}
}
用法:
.sheet {
VStack {
...
}.isModalInPresentation(true)
}
答案 4 :(得分:0)
从理论上讲,这可能会对您有所帮助(我没有尝试过)
private var isDisplayedBind: Binding<Bool>{ Binding(get: { true }, set: { _ = $0 }) }
和用法:
content
.sheet(isPresented: isDisplayedBind) { some sheet }