SwiftUI中Sheet含Form+TextField时presentationDetent异常问题咨询
SwiftUI Sheet设置.medium档位失效问题(Form包含TextField时)
我尝试用.sheet展示一个设置了.medium级presentationDetent的Form,但只要Form里包含TextField,Sheet就会强制以.large级别展示。移除TextField后Sheet能正常显示.medium档位,保留TextField但去掉Form时,.medium也能正常生效,推测是Form内的TextField触发了这个问题。
问题复现代码
struct ListViewTriggerSheet: View { private var dataModel = ["Inner One", "Inner Two", "Inner Three", "Inner Four", "Inner Five", "Inner Six"] @State private var shouldPresentSheet = false var body: some View { LazyVGrid(columns: [GridItem(.flexible(minimum: 40.00), spacing: 10), GridItem(.flexible(minimum: 40.00), spacing: 10)]) { ForEach(dataModel, id: \.self) { innerItem in InnerListItemView(data: innerItem) .onTapGesture { shouldPresentSheet = true } } .sheet(isPresented: $shouldPresentSheet) { } content: { ListViewSheetView(textString: "Foo") .presentationDetents([.medium]) } } } } struct InnerListItemView : View { @State var data: String var body: some View { Text(data) } } struct ListViewSheetView : View { @State var textString: String var body: some View { Form { Text(textString) // Remove TextField() below and the .sheet behaves differently TextField("Beskrivning", text: $textString) } } } #Preview { ListViewTriggerSheet() }
问题原因
这是SwiftUI的一个已知行为:当Sheet中的内容包含需要唤起键盘的控件(如TextField)时,系统会自动调整Sheet尺寸以适配键盘,从而忽略手动设置的.medium档位。而Form容器本身具备自动适配内容的布局特性,两者结合后会强制Sheet展开到.large档位。
解决方案
1. 限制Form的最大高度
给Form设置对应.medium档位的最大高度,阻止系统自动扩展Sheet:
struct ListViewSheetView : View { @State var textString: String var body: some View { Form { Text(textString) TextField("Beskrivning", text: $textString) } .frame(maxHeight: UIScreen.main.bounds.height * 0.5) // 匹配.medium的大致高度 } }
2. 用自定义容器替代Form
如果不需要Form的原生样式,改用VStack等自定义容器,避免Form的自动布局干扰:
struct ListViewSheetView : View { @State var textString: String var body: some View { VStack(spacing: 16) { Text(textString) TextField("Beskrivning", text: $textString) .textFieldStyle(.roundedBorder) .padding(.horizontal) } .padding() } }
3. 强制锁定Sheet尺寸
结合拖拽指示器和禁用交互式关闭,配合固定高度进一步锁定档位:
// 在Sheet的content闭包中修改 ListViewSheetView(textString: "Foo") .presentationDetents([.medium]) .presentationDragIndicator(.visible) .interactiveDismissDisabled()
内容的提问来源于stack exchange,提问作者Per Lindgren
相关产品推荐
相关产品推荐

