You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:43:18