SwiftUI自定义键盘适配Modifier导致Form出现白色空白问题求助
SwiftUI Form键盘弹出时出现空白区域问题
问题描述
在SwiftUI的Form视图中使用自定义View Modifier实现键盘弹出时上移视图,避免文本框被遮挡,此前功能正常,但现在键盘弹出时,键盘与文本框之间出现奇怪的白色空白区域。
问题演示
- 使用Modifier后异常情况:

- 未使用Modifier时(键盘遮挡文本框):

相关代码
MainView
var body: some View { NavigationStack{ ZStack{ // 根据索引切换视图 switch selectedIndex { case 0 : Text("HOME") case 1 : Logbook(dm: dm) case 2 : AddFlightView(dm: dm) default: Text("Default") } // 底部TabBar覆盖层 VStack{ Spacer() BottomBar(selectedIndex: $selectedIndex, items: $items) .cornerRadius(15) .padding(.horizontal) .shadow(color: Color.darkTextColorMain.opacity(0.1), radius: 10, x: 10, y: 5) } } .navigationTitle(titleChange(selectedIndex: selectedIndex)) } }
AddFlightView
var body: some View { Form{ Section("Flight") { Picker("选择 ", selection: $selected) { ForEach(DutyType.allCases,id: \.self) { type in Text(stringPicker(dutyType:type)) } } DatePicker(selection: $flightDate, displayedComponents: .date) { Text("选择日期") }.environment(\.timeZone, TimeZone(abbreviation: "UTC")!) } Section("Departure and Destination") { HStack{ Text("出发机场") TextField(text: $departure_Apt) { Text("出发机场") }.multilineTextAlignment(.trailing) } HStack{ Text("到达机场") TextField(text: $arrival_Apt) { Text("到达机场") }.multilineTextAlignment(.trailing) } } Section("时间选择"){ DatePicker(selection: $chockoff, displayedComponents: .hourAndMinute) { Text("滑出时间 \(convertDateToString(date: chockoff))") }.environment(\.timeZone, TimeZone(abbreviation: "UTC")!) DatePicker(selection: $chockin, in: convertToUTCDate(dateToConvert: Date.now)... , displayedComponents: .hourAndMinute) { Text("UTC选择时间: \(convertDateToString(date: chockin))") }.environment(\.timeZone, TimeZone(abbreviation: "UTC")!) TextField("添加", text: $test) // .textContentType(.oneTimeCode) .keyboardType(.numberPad) Spacer() } } .modifier(Keyboard()) }
Keyboard ViewModifier
struct Keyboard : ViewModifier { @State var offset: CGFloat = 0 func body(content: Content) -> some View { content.padding(.bottom,offset).onAppear(perform: { NotificationCenter.default.addObserver(forName: UIResponder.keyboardDidShowNotification, object: nil, queue: .main) { notification in let val = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect let height = val.height self.offset = height } NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { notification in self.offset = 0 } }) } }
问题原因及解决方法
核心原因
自定义Modifier直接给Form添加了等于键盘高度的底部padding,但SwiftUI的Form本身已内置键盘适配逻辑(尤其是在NavigationStack中),两者叠加导致视图过度上移,出现空白区域。另外,keyboardDidShow获取的键盘高度包含设备底部安全区域高度(如带HomeIndicator的机型),而Form内置适配已处理该部分,重复添加会造成多余偏移。
解决方法
方法1:移除自定义Modifier,依赖SwiftUI内置适配
直接删掉.modifier(Keyboard()),同时给底部自定义TabBar添加忽略键盘安全区域的设置,确保Form内置适配能正确计算可用空间:
BottomBar(selectedIndex: $selectedIndex, items: $items) .cornerRadius(15) .padding(.horizontal) .shadow(color: Color.darkTextColorMain.opacity(0.1), radius: 10, x: 10, y: 5) .ignoresSafeArea(.keyboard) // 添加此行
同时建议移除AddFlightView中Time Selection Section里的Spacer(),避免Form内部出现多余空白。
方法2:修复自定义Modifier的偏移计算
如果必须保留自定义Modifier,需修正偏移量计算逻辑,减去安全区域高度:
struct Keyboard: ViewModifier { @State private var keyboardHeight: CGFloat = 0 func body(content: Content) -> some View { content .padding(.bottom, keyboardHeight) .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { notification in guard let userInfo = notification.userInfo, let frame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } let safeAreaBottom = UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0 keyboardHeight = frame.height - safeAreaBottom } .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in keyboardHeight = 0 } } }
内容的提问来源于stack exchange,提问作者Damiano Miazzi
相关产品推荐
相关产品推荐

