SwiftUI中键盘弹出时如何实现整个视图上移?
SwiftUI自定义Sheet键盘弹出时视图上推解决方案
问题描述
应用中自定义Sheet内的TextField点击弹出键盘时,视图显示异常(截图:
),需要实现键盘弹出时将整个Sheet视图向上推动,但常规方案未生效。
解决方案
核心思路是监听键盘高度变化,动态调整Sheet的偏移量,同时修正Sheet的布局设置以响应安全区域变化:
修改后的CustomSheet代码
import SwiftUI import Design import Utilities public struct CustomSheet<Item: Hashable, Content: View>: View { private let size: CGSize private var item: Binding<Item?> private var content: (Item) -> Content // 存储键盘高度,用于动态调整视图偏移 @State private var keyboardHeight: CGFloat = 0 public init( size: CGSize, item: Binding<Item?>, @ViewBuilder content: @escaping (Item) -> Content ) { self.size = size self.item = item self.content = content } public var body: some View { ZStack(alignment: .bottom) { background VStack(spacing: 30) { Button { withAnimation { item.wrappedValue = nil } } label: { Image(systemName: "xmark") .tint(Colors.jaffa) } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) .padding(20) if let item = item.wrappedValue { content(item) } } .padding(.horizontal) .frame(width: size.width, height: size.height * 0.55) .background { RoundedRectangle(cornerRadius: 50) .fill(Colors.white) } // 动态计算偏移:显示时根据键盘高度上移,隐藏时滑出屏幕 .offset(y: item.wrappedValue != nil ? (keyboardHeight > 0 ? -keyboardHeight : 0) : size.height * 1) // 监听键盘弹出/收起事件 .onAppear { let showObserver = NotificationCenter.default.addObserver( forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main ) { notification in guard let userInfo = notification.userInfo, let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double ?? 0.25 withAnimation(.easeInOut(duration: animationDuration)) { keyboardHeight = keyboardFrame.height } } let hideObserver = NotificationCenter.default.addObserver( forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main ) { notification in let animationDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double ?? 0.25 withAnimation(.easeInOut(duration: animationDuration)) { keyboardHeight = 0 } } // 存储观察者,避免内存泄漏 NotificationCenter.default.addObserver(self, selector: #selector(removeObservers), name: UIApplication.willTerminateNotification, object: nil) } .onDisappear { removeObservers() } } } @objc private func removeObservers() { NotificationCenter.default.removeObserver(self) } } extension CustomSheet { private var background: some View { Rectangle() .fill(.ultraThinMaterial) .ignoresSafeArea() .opacity((item.wrappedValue != nil) ? 1 : 0) } }
关键修改说明
- 添加键盘高度监听:通过
NotificationCenter监听键盘的弹出和收起事件,获取键盘高度和动画参数,同步更新keyboardHeight状态。 - 动态调整偏移量:修改Sheet的
offset属性,当键盘弹出时,将Sheet向上偏移对应高度,避免被键盘遮挡;键盘收起时恢复原位。 - 修正背景布局:移除背景的
edgesIgnoringSafeArea(.bottom),让Sheet正确响应底部安全区域变化,避免布局错位。 - 内存泄漏防护:在视图消失或应用终止时移除通知观察者,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Sonix
相关产品推荐
相关产品推荐

