SwiftUI中ScrollView内的TextEditor输入长文本时被键盘遮挡的问题求助
SwiftUI中ScrollView内的TextEditor输入长文本时被键盘遮挡的问题求助
大家好,我现在在做一个SwiftUI的Demo,里面用ScrollView包裹了一组可编辑的多行文本框(基于TextEditor实现的自定义MultilineTextFieldView)。正常情况下UI表现都没问题,但只要其中一个文本框输入了大量内容(比如20-25行),键盘就会开始遮挡TextEditor的底部区域,我没法滚动到文本末尾去查看或编辑。
下面是我简化后的代码:
struct ContentView: View { @State private var textItems: [TextItem] = [ TextItem(id: 1, text: "First text field"), TextItem(id: 2, text: "Second text field"), // 更多条目... ] @State private var keyboardHeight: CGFloat = 0 var body: some View { NavigationView { ScrollViewReader { proxy in ScrollView { LazyVStack(spacing: 16) { ForEach($textItems) { $item in MultilineTextFieldView( text: $item.text, placeholder: "Enter text for item \(item.id)...", onEditingChanged: { isEditing in if isEditing { withAnimation { proxy.scrollTo(item.id, anchor: .center) } } }, onTextChanged: {} ) .id(item.id) } } .padding() .padding(.bottom, keyboardHeight > 0 ? keyboardHeight - 34 : 0) } .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { notification in if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue { let keyboardRect = keyboardFrame.cgRectValue withAnimation { keyboardHeight = keyboardRect.height } } } .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in withAnimation { keyboardHeight = 0 } } } .navigationTitle("Multiline Text Fields") } } } struct MultilineTextFieldView: View { @Binding var text: String let placeholder: String let onEditingChanged: (Bool) -> Void let onTextChanged: () -> Void @FocusState private var isFocused: Bool var body: some View { VStack(alignment: .leading, spacing: 8) { HStack { Text("Text Field") Spacer() Text("\(text.count) chars") } ZStack(alignment: .topLeading) { RoundedRectangle(cornerRadius: 12) .fill(Color(.systemGray6)) .stroke(isFocused ? Color.blue : Color.clear, lineWidth: 2) if text.isEmpty { Text(placeholder) .foregroundColor(.secondary) .padding(.horizontal, 16) .padding(.vertical, 12) .allowsHitTesting(false) } TextEditor(text: $text) .padding(.horizontal, 12) .padding(.vertical, 8) .background(Color.clear) .focused($isFocused) .onChange(of: isFocused, perform: onEditingChanged) .onChange(of: text, perform: { _ in onTextChanged() }) .fixedSize(horizontal: false, vertical: true) } .frame(minHeight: 40) } } } struct TextItem: Identifiable { let id: Int var text: String }
我已经尝试过的解决方法:
- 给
TextEditor添加.fixedSize(horizontal: false, vertical: true)修饰符 - 监听键盘高度变化,给
ScrollView的内容动态添加底部内边距 - 借助
ScrollViewReader,在文本框开始编辑时自动滚动到当前条目(锚点设为.center) - 通过
NotificationCenter监听键盘的显示/隐藏通知来更新键盘高度
但问题依然存在:当文本框内容过长时,键盘会遮挡文本框底部,我无法滚动到文本末尾进行编辑。
我期望的效果是:当前处于编辑状态的TextEditor(哪怕内容很长)能自动保持在键盘上方完全可见,不会被遮挡,我可以正常滚动编辑全部文本内容。
补充说明:我试过用UIKit的UITextView通过UIViewRepresentable来实现相同功能,是可以正常工作的,但我想尽量用SwiftUI原生的TextEditor来解决这个问题。
内容来源于stack exchange
相关产品推荐
相关产品推荐

