iOS 14 SwiftUI 键盘自动提升视图

Posted

技术标签:

【中文标题】iOS 14 SwiftUI 键盘自动提升视图【英文标题】:iOS 14 SwiftUI Keyboard lifts view automatically 【发布时间】:2021-01-05 13:54:19 【问题描述】:

我在视图中使用 TextField,当它成为第一响应者时,它会离开视图,如下 GIF 所示。

有什么办法可以摆脱这种行为吗?

这是我的代码

NavigationView(content: 
    ZStack
        MyTabView(selectedIndex: self.$index)
            .view(item: self.item1) 
                NewView(title: "Hello1").navigationBarTitle("")
                    .navigationBarHidden(true)
            
            .view(item: self.item2) 
                NewView(title: "Hello2").navigationBarTitle("")
                    .navigationBarHidden(true)
            
            .view(item: self.item3) 
                NewView(title: "Hello3").navigationBarTitle("")
                    .navigationBarHidden(true)
            
    .navigationBarHidden(true)
    .navigationBarTitle("")
).ignoresSafeArea(.keyboard, edges: .bottom)

// 新视图

struct NewView:View 
    @State var text:String = ""
    var title:String
    var body: some View 
        VStack 
            Spacer()
            Text("Hello")
            TextField(title, text: self.$text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
        .padding()
        .onAppear 
            debugPrint("OnApper \(self.title)")
        
    

【问题讨论】:

为什么要摆脱这种行为?如果您不抬起文本字段,它会被键盘覆盖并且您无法分辨您正在输入的内容,或者使用点击/拖动手势来更改选择。它使编辑无法使用。 因为在 ios13 中,键盘只是简单地自动切换......正如预期的那样。我们不得不再次为 ios14 添加 if 语句。而且我相信 ios15 还会有更多的 if 语句。 【参考方案1】:

要使.ignoresSafeArea 工作,您需要填充所有可用区域(例如,使用Spacer)。


以下不起作用(没有 Spacers,只是一个 TextField):

struct ContentView: View 
    @State var text: String = ""
    var body: some View 
        VStack 
            TextField("asd", text: self.$text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
        
        .ignoresSafeArea(.keyboard, edges: .bottom)
    


但是,当您添加 Spacers(填充所有可用空间)时,它会起作用

struct ContentView: View 
    @State var text: String = ""
    var body: some View 
        VStack 
            Spacer()
            TextField("asd", text: self.$text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            Spacer()
        
        .ignoresSafeArea(.keyboard, edges: .bottom)
    


如果您不想使用 Spacers,也可以使用 GeometryReader

struct ContentView: View 
    @State var text: String = ""
    var body: some View 
        GeometryReader  _ in
            ...
        
        .ignoresSafeArea(.keyboard, edges: .bottom)
    

【讨论】:

如果你有这个修改器,所有它都不起作用。 (.edgesIgnoringSafeArea(.all))【参考方案2】:

您应该在 ZStack 上应用修饰符,NOT NavigationView

NavigationView(content: 
    ZStack
        ,,,
    .navigationBarHidden(true)
    .navigationBarTitle("")
    .ignoresSafeArea(.keyboard, edges: .bottom) // <- This line moved up
)

完整的工作示例:

struct ContentView: View 
    @State var text = ""
    var body: some View 
        VStack
            Spacer()
            Text("Hello, World")
            TextField("Tap to test keyboard ignoring", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
        
        .padding()
        .ignoresSafeArea(.keyboard, edges: .bottom)
    

【讨论】:

修饰符根本不起作用。 TextField 仍然向上移动.. :( 可能你错过了原始代码实现。 I. 添加了完整的代码演示,以便您可以重现它;) 如果我在视图中包含一些这样的行:ScrollView LazyVStack Rows ... 使用 ignoresSafeArea 将导致行中的闪烁,这是显而易见且令人讨厌的【参考方案3】:

结合此处发布的答案并考虑this question,最终对我有用的是以下(Xcode 12.4、iOS 14.4):

GeometryReader  _ in
    VStack 
        Spacer()
        TextField("Type something...", text: $value)
        Spacer()
    .ignoresSafeArea(.keyboard, edges: .bottom)

两个垫片都用于垂直居中文本字段。

仅使用 GeometryReader 或 ignoresSafeArea 修饰符并不能解决问题,但在如上所示将它们全部放在一起后,最终视图在键盘出现时无法向上移动。

【讨论】:

【参考方案4】:

这就是我想出来的:

GeometryReader  _ in
    ZStack 
        //PUT CONTENT HERE
    .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)

这似乎对我有用。在这种情况下,您无需检查 iOS 14 的可用性。

【讨论】:

以上是关于iOS 14 SwiftUI 键盘自动提升视图的主要内容,如果未能解决你的问题,请参考以下文章

在 SwiftUI 中显示键盘上方的视图 [关闭]

仅在 iOS 14、SwiftUI 时显示一些视图

SwiftUI捕获键盘提交动作在iOS15之前和之后的兼容实现

在 SwiftUI iOS 14 中旋转视图

SwiftUI禁止用户关闭sheet弹出视图在iOS14.6+失效的巧妙解决

SwiftUI禁止用户关闭sheet弹出视图在iOS14.6+失效的巧妙解决