swift 显示软键盘时,导航视图中的文本输入焦点会反弹回初始视图

yzxexxkh  于 2023-09-29  发布在  Swift
关注(0)|答案(2)|浏览(68)

下面的代码创建了一个简单的NavigationView结构,其中包含两个子视图:LoggedOutView带有一个按钮,该按钮通过一个简单的输入字段指向RegistrationView。我使用GeometryReader是因为如果不直接指定许多使用的UI元素的框架尺寸,它将无法正确布局(例如,LoggedOutView中的底部元素应该始终保持在底部)。此外,视图应该在一个ScrollView的弹性拖动效果,但似乎这对问题没有影响。
问题是,当导航到RegistrationView并在模拟器(或设备)上使用软键盘时聚焦输入字段时,导航视图立即反弹回LoggedOutView(或者更确切地说,ContentView自动转到LoggedOutView)。在模拟器中未激活软键盘时不会发生该问题,因此看起来是因为软键盘显示布局存在冲突,迫使导航视图返回。
我在Xcode中没有得到这个问题的错误日志,我不知道为什么会发生这个问题,但也许我的LoggedOutView没有正确设置?对于SwiftUI 2,问题发生在iOS 14和15上。

ContentView

import SwiftUI

enum NavigationViewTarget: String {
    case ContentView
    case LoggedOutView
    case RegistrationView
}

struct ContentView: View {
    @State private var navigationViewTarget: NavigationViewTarget? = .ContentView
    
    var body: some View {
        GeometryReader {
            geo in
            NavigationView {
                NavigationLink(destination: LoggedOutView(), tag: .LoggedOutView, selection: $navigationViewTarget) { EmptyView() }
                .hidden()
                .navigationBarHidden(true)
            }
            .frame(width: geo.size.width, height: geo.size.height)
            .onAppear(perform: onAppear)
        }
    }
    
    private func onAppear() {
        navigationViewTarget = .LoggedOutView
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

LoggedOutView

import SwiftUI

struct LoggedOutView: View {
    @State private var navigationViewTarget: NavigationViewTarget? = .LoggedOutView
    
    var body: some View {
        GeometryReader {
            geo in

            ScrollView(showsIndicators: false) {
                VStack(alignment: .leading) {
                    Spacer().frame(maxWidth: .infinity, maxHeight: 28.0)
                    
                    RoundedRectangle(cornerRadius: 10)
                        .scaledToFit()
                        .frame(width: abs(geo.size.width - 60), height: abs(geo.size.width - 60))
                        .padding(.leading, 30)
                        .padding(.trailing, 30)
                        .foregroundColor(.gray)

                    Spacer().frame(maxWidth: .infinity)
                        .layoutPriority(-1)
                    
                    HStack {
                        NavigationLink(destination: RegistrationView(), tag: .RegistrationView, selection: $navigationViewTarget) { EmptyView() }.hidden()

                        Button(action: { navigationViewTarget = .RegistrationView }) {
                            Spacer()
                            Text("Register").padding(16)
                            Spacer()
                        }
                        .frame(height: 45)
                        .background(.red)
                        .foregroundColor(.white)
                    }
                    .frame(width: abs(geo.size.width - 60))
                    .padding(.leading, 30)
                    .padding(.trailing, 30)

                    Spacer().frame(maxWidth: .infinity, minHeight: 90)
                        .layoutPriority(-2)

                    VStack {
                        RoundedRectangle(cornerRadius: 10)
                            .frame(width: abs(geo.size.width - 60), height: 50)
                            .padding(.leading, 30)
                            .padding(.trailing, 30)
                            .foregroundColor(.gray)
                    }
                    .frame(width: geo.size.width)
                    .padding(.bottom, 16)
                }
                .frame(height: abs(geo.size.height - geo.safeAreaInsets.bottom))
                .padding(30)

            }
            .frame(width: geo.size.width)
            .navigationBarHidden(true)
            .navigationBarTitleDisplayMode(.inline)
            .navigationViewStyle(StackNavigationViewStyle())
        }
    }
}

struct LoggedOutView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView
        {
            LoggedOutView()
                .navigationBarTitleDisplayMode(.inline)
                .navigationViewStyle(StackNavigationViewStyle())
                .navigationBarHidden(true)
        }
    }
}

注册查看

import SwiftUI

struct RegistrationView: View {
    @State var email = ""
    var body: some View {
        GeometryReader {
            geo in
            ScrollView(showsIndicators: false) {
                VStack(alignment: .leading) {
                    Spacer().frame(maxWidth: .infinity, maxHeight: 10)

                    VStack(alignment: .leading, spacing: 16) {
                        VStack(alignment: .leading, spacing: 2) {
                            TextField("Email", text: $email)
                        }
                    }
                }
                .padding(30)
            }
            .frame(width: geo.size.width, height: geo.size.height)
            .navigationBarTitleDisplayMode(.inline)
            .navigationViewStyle(StackNavigationViewStyle())
            .navigationBarHidden(false)
        }
        .navigationBarTitle("Registration", displayMode: .inline)
    }
}

struct RegistrationView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView
        {
            RegistrationView()
                .navigationBarTitleDisplayMode(.inline)
                .navigationViewStyle(StackNavigationViewStyle())
        }
    }
}
f0brbegy

f0brbegy1#

我发现了一个修复程序,使它的工作,但只有在iOS 15。从ContentView中完全删除Geo reader和one frame属性似乎可以解决整个问题。我仍然不知道为什么它不喜欢我用.frame(width: geo.size.width, height: geo.size.height)显式地为NavigationView设置宽度和高度。
编辑:似乎每当使用geo阅读器并且框架高度设置在geo的某个地方时,这个问题就一定会发生在导航视图中。我最终删除了所有的几何阅读器,并依靠window.width和height代替。

i2byvkas

i2byvkas2#

您需要将NavigationView从GeometryReader中拉出。
就在

var body: some View {
  NavigationView {
    GeometryReader { geometry in
      ScrollView {

这样不对

var body: some View {
  GeometryReader { geometry in
    NavigationView {
      ScrollView {

相关问题