TextEditor 在 SwiftUI 中被键盘遮挡。

6
我希望我的文本编辑器能够避免出现屏幕键盘,这样我就可以输入并查看它 :) 我猜我可以使用iOS 15进行定位。我相信我试过互联网上许多处理键盘事件并尝试调整一些填充/偏移等的解决方案,但它们都对我无效。似乎文本字段完全没有这个问题(至少在iOS 15中),因为它们保持可见状态(容器视图根据需要滚动),即使键盘出现在屏幕上也是如此。我不知道为什么这个基本功能不能免费提供...UIKit / UITextView似乎不需要开发人员额外关注就可以工作。
那么,为了能够立即点击下面示例中的第3个文本编辑器(在“注释”部分),开始输入而无需手动滚动视图以使编辑器对我可见,我需要做什么?
import SwiftUI

struct ContentView: View {
    @State private var text: String = ""
    
    init() {
        UITextView.appearance().backgroundColor = .clear
    }
    
    var body: some View {
        Form {
            TextEditor(text: $text)
                .frame(height: 300)
                .background(.yellow)
            TextEditor(text: $text)
                .frame(height: 300)
                .background(.mint)
            Section("Notes") {
                TextEditor(text: $text)
                    .frame(height: 300)
                    .background(.teal)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
2个回答

7

TextEditor本身就是一个滚动视图,所以操作系统可能会对移动/偏移的位置感到困惑。在这种情况下(或者当您将所有这些编辑器包装在ForEach中时),一种可能的方法是使用可聚焦状态并显式强制将所有内容向上移动。

已测试通过Xcode 13.4 / iOS 15.5

演示

以下是主要部分:

        TextEditor(text: $text).id(2)
            .focused($inFocus, equals: 2)
            .frame(height: 300)
            .background(.teal)
        
        if inFocus == 2 {
            Color.clear.frame(height: 300)
        }
    }
    .onChange(of: inFocus) { id in
        withAnimation {
            sp.scrollTo(id)
        }
    }

完整的测试代码在这里


谢谢,这确实有效。但是在我发布了示例代码后,我意识到我需要将我的TextEditors放在Form内(而不是ScrollView内),并且使用Form时,建议的解决方案在第一次尝试时不起作用(当应用程序刚启动时),但如果您继续切换焦点,它会开始工作。请问您知道为什么在TextEditors位于Form内时,第一次不起作用吗? - Sergey
1
Color.clear.frame(height: 300) 的目的是什么?我问这个问题是因为在 ScrollView 中使用 TextEditors,即使没有 if inFocus == 2 { Color.clear.frame(height: 300) },你的解决方案也能正常工作。 - Sergey
@Sergey 如果你的文本编辑器下面没有300高度的视图,滚动视图就没有空间可以扩展。因此,通过添加Color.clear,它会增加空间,而你看不到它。300是键盘占用的高度。 - undefined

0
为了利用ScrollView的自动键盘避让功能,同时确保Form在ScrollView内满足要求(默认情况下不满足),您可以使用框架为Form设置固定宽度。下面的示例设置了一个与屏幕大小相匹配的框架,但如果需要,您可以尝试调整大小。
let screenSize = UIScreen.main.bounds.size
    
    var body: some View {
        ScrollView {
            Form {
                TextEditor(text: $text)
                    .frame(height: 300)
                    .background(.yellow)
                TextEditor(text: $text)
                    .frame(height: 300)
                    .background(.mint)
                Section("Notes") {
                    TextEditor(text: $text)
                        .frame(height: 300)
                        .background(.teal)
                }
            }
            .frame(width: screenSize.width, height: screenSize.height)
        }
    }

如果我使用ScrollView包装表单,我会得到一个空白的白屏,什么也没有显示。 - Sergey
@Sergey 当然,我忘记了Form和ScrollView不兼容。我已经更新了我的答案并提供了解决方法。 - James William
很遗憾,这对我不起作用。 - Sergey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接