在SwiftUI中使用普通键盘从字段移动时,使用小数的文本字段键盘未滚动到可见区域

zed5wv10  于 2023-01-25  发布在  Swift
关注(0)|答案(2)|浏览(134)

bounty将在3天后过期。此问题的答案可获得+50声望奖励。fs_tigre正在寻找此问题的更详细答案:我想知道这是否是一个错误,如果有一个修复它,因为我不能找到任何答案在网上。我想知道其他人如何管理这种情况时,他们有很多文本字段。

如果前一个字段使用的是普通键盘,那么为什么Field 3Field 5在活动时不可见呢?
在下面的代码中,如果点击Field 1,并且在点击Field 3Field 5之后立即点击,则它们将不可见;它们被键盘隐藏了。
请注意,Field 3Field 5使用decimalPad键盘,而其余字段使用标准键盘。

struct TextFieldScrollingIssue: View {
    @State private var testInput:String = ""
    
    var body: some View {
        VStack{
            Form {
                TextField("Field 1", text:$testInput)
                Spacer()
                Spacer()
                Spacer()
                Spacer()
                Spacer()
                Spacer()
                Spacer()
                Section(header: Text("Section 1: ")) {
                    TextField("Field 2", text:$testInput)
                    TextField("Field 3", text:$testInput)
                        .keyboardType(.decimalPad)
                }
                
                Section(header: Text("Section 2: ")) {
                    TextField("Field 4", text:$testInput)
                    TextField("Field 5", text:$testInput)
                        .keyboardType(.decimalPad)
                }
            }
        }
    }
}
qgelzfjb

qgelzfjb1#

我认为滚动机制是混乱的,因为您对所有TextFields使用了相同的变量。显然,在生产中,您永远不会遇到这种情况。修复方法很简单,使用不同的变量:

struct TextFieldScrollingIssue: View {
    @FocusState var isFocused: String?
    @State private var testInput:String = ""
    @State private var decimalInput:String = ""
    
    var body: some View {
        VStack{
            ScrollViewReader { scroll in
                Form {
                    TextField("Field 1", text:$testInput)
                        .id("Field 1")
                        .focused($isFocused, equals: "Field 1")
                    Text(isFocused?.description ?? "nil")
                    Spacer()
                    Spacer()
                    Spacer()
                    Spacer()
                    Spacer()
                    Spacer()
                    Section(header: Text("Section 1: ")) {
                        TextField("Field 2", text:$testInput)
                            .id("Field 2")
                            .focused($isFocused, equals: "Field 2")
                        TextField("Field 3", text:$decimalInput)
                            .id("Field 3")
                            .focused($isFocused, equals: "Field 3")
                            .keyboardType(.decimalPad)
                    }
                    
                    Section(header: Text("Section 2: ")) {
                        TextField("Field 4", text:$testInput)
                            .id("Field 4")
                            .focused($isFocused, equals: "Field 4")
                        TextField("Field 5", text:$decimalInput)
                            .id("Field 5")
                            .focused($isFocused, equals: "Field 5")
                            .keyboardType(.decimalPad)
                    }
                }
                .onChange(of: isFocused) { _ in
                    if let isFocused = isFocused {
                        DispatchQueue.main.async {
                            withAnimation {
                                scroll.scrollTo(isFocused)
                            }
                        }
                    }
                }
            }
        }
    }
}

编辑:
根据评论,我能够重现。编辑代码使用一个ScrollviewReader@FocusState和视图id来纠正。

kwvwclae

kwvwclae2#

问题是,当你点击字段3或字段5时,键盘会出现并将表单内容向上推。由于字段3和字段5位于表单的底部,它们被键盘遮住了。有几种方法可以解决这个问题

  • 方法一

使用ScrollView Package 窗体并将.keyboardDismissMode设置为.interactive。这将允许用户通过向下滑动ScrollView来关闭键盘。

ScrollView(.vertical, showsIndicators: false) {
    Form {
        //...
    }
}.keyboardDismissMode(.interactive)
  • 方法二

将窗体 Package 为GeometryReader,并使用其safeAreaInsets调整键盘出现时窗体的偏移

var body: some View {
    GeometryReader { geometry in
        VStack {
            Form {
                //...
            }
        }
        .offset(y: -geometry.safeAreaInsets.bottom)
    }
}
  • 方法三

使用KeyboardResponder类侦听键盘事件,并在键盘出现时调整窗体的偏移量:

struct TextFieldScrollingIssue: View {
    @State private var testInput:String = ""
    @ObservedObject var keyboard = KeyboardResponder()

    var body: some View {
        VStack {
            Form {
                //...
            }
            .offset(y: -keyboard.currentHeight)
        }
    }
}

class KeyboardResponder: ObservableObject {
    private var notificationCenter: NotificationCenter
    @Published private(set) var currentHeight: CGFloat = 0

    init(center: NotificationCenter = .default) {
        notificationCenter = center
        notificationCenter.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        notificationCenter.addObserver(self, selector: #selector(keyBoardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    @objc func keyBoardWillShow(notification: Notification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            currentHeight = keyboardSize.height
        }
    }

    @objc func keyBoardWillHide(notification: Notification) {
        currentHeight = 0
    }
}

相关问题