SwiftUI中键盘弹出时如何调整ScrollView内边距?
解决SwiftUI中ScrollView里TextField被键盘遮挡的问题
这个问题我做项目时也碰到过,确实挺闹心的——SwiftUI默认的ScrollView不会自动根据键盘弹出/收起调整自身位置,不过有两种很实用的解决办法,根据你的iOS版本需求选就行:
方法一:iOS 15+ 原生快捷方案
从iOS 15开始,Apple给ScrollView加了一个超方便的修饰符.keyboardPadding(),直接给你的ScrollView加上这个,系统会自动处理键盘弹出时的内边距调整,代码改起来特别简单:
var body: some View { ScrollView { Text("SomeParameter1") TextField("", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) Text("SomeParameter2") TextField("", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) Text("SomeParameter3") TextField("", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) Text("SomeParameter4") TextField("", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) } .keyboardPadding() // 就加这一行! }
这个方法完全不用自己写监听逻辑,系统帮你搞定一切,推荐在支持iOS15及以上的项目里用。
方法二:兼容iOS 13+ 的自定义监听方案
如果你的项目需要兼容更低版本的iOS,那可以通过监听键盘的通知来动态调整ScrollView的底部内边距。首先我们写一个管理键盘状态的ObservableObject:
class KeyboardManager: ObservableObject { @Published var keyboardHeight: CGFloat = 0 init() { // 监听键盘弹出和收起的通知 NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil ) } @objc private func keyboardWillShow(_ notification: Notification) { // 从通知里获取键盘的高度 guard let userInfo = notification.userInfo, let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } keyboardHeight = keyboardFrame.height } @objc private func keyboardWillHide(_ notification: Notification) { keyboardHeight = 0 } }
然后在你的View里使用这个管理器,动态设置ScrollView的底部内边距:
struct YourView: View { @State private var text = "" // iOS14+用@StateObject,iOS13的话换成@ObservedObject @StateObject private var keyboardManager = KeyboardManager() var body: some View { ScrollView { Text("SomeParameter1") TextField("", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) Text("SomeParameter2") TextField("", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) Text("SomeParameter3") TextField("", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) Text("SomeParameter4") TextField("", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) } // 根据键盘高度设置底部内边距 .padding(.bottom, keyboardManager.keyboardHeight) // 加上动画,让内边距变化更顺滑 .animation(.easeOut, value: keyboardManager.keyboardHeight) } }
另外你提到用List没解决问题,其实List默认是会自动调整的,但如果你的List用了自定义样式或者嵌套了其他容器,可能会失效,而ScrollView作为更基础的容器,确实需要手动处理这类适配。
内容的提问来源于stack exchange,提问作者savmex
相关产品推荐
相关产品推荐

