【问题标题】:Keyboard Listener in List in SwiftUISwiftUI 列表中的键盘侦听器
【发布时间】:2019-09-02 07:39:18
【问题描述】:

我的列表包含 5 个文本字段、一个图像和一个按钮。以下是来自AppCoda. 的引用我在这里面临的问题是当键盘启动时我无法显示最后一个文本字段。找到了许多相关的答案,但没有一个是有帮助的。另外,我想在单击或长按时从列表中删除动画。

Video Here

任何帮助将不胜感激!

【问题讨论】:

    标签: ios swiftui


    【解决方案1】:

    我有您添加的结帐链接。 Blaaahhhhh,由于某些语法已更改,因此非常烦人。无论如何,我不会解释你已经完成的整个教程。

    我参考了这里:https://stackoverflow.com/a/56721268/6144643

    更新LabelTextField代码如下。

    struct LabelTextField: View {
    
        var label: String = ""
        var placeHolder: String = ""
        var tag: Int? = nil
        var kGuardian: KeyboardGuardian
        @State var textField: String = ""
    
        var body: some View {
            VStack(alignment: .leading) {
                Text(label)
                    .font(.headline)
                TextField(placeHolder, text: $textField, onEditingChanged: {
                    if $0 { self.kGuardian.showField = self.tag! }
                })
                    .padding(.all)
                    .background(Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0))
                    .cornerRadius(5.0)
                }
            .padding()
            .listRowInsets(EdgeInsets())
        }
    }
    

    更新ContentView中的代码以初始化LabelTextField如下:

    import SwiftUI
    import Combine
    
    struct ContentView: View {
    
        @ObservedObject private var kGuardian = KeyboardGuardian(textFieldCount: 5)
    
        var body: some View {
    
            NavigationView {
                List {
    
                    VStack(alignment: .leading) {
                        LabelTextField(label: "NAME", placeHolder: "Fill in the restaurant name", tag: 0, kGuardian: kGuardian, textField: "")
                            .background(GeometryGetter(rect: $kGuardian.rects[0]).foregroundColor(.clear))
    
                        LabelTextField(label: "TYPE", placeHolder: "Fill in the restaurant type", tag: 1, kGuardian: kGuardian, textField: "")
                            .background(GeometryGetter(rect: $kGuardian.rects[1]).foregroundColor(.clear))
    
                        LabelTextField(label: "ADDRESS", placeHolder: "Fill in the restaurant address", tag: 2, kGuardian: kGuardian, textField: "")
                            .background(GeometryGetter(rect: $kGuardian.rects[2]).foregroundColor(.clear))
    
                        LabelTextField(label: "PHONE", placeHolder: "Fill in the restaurant phone", tag: 3, kGuardian: kGuardian, textField: "")
                            .background(GeometryGetter(rect: $kGuardian.rects[3]).foregroundColor(.clear))
    
                        LabelTextField(label: "DESCRIPTION", placeHolder: "Fill in the restaurant description", tag: 4, kGuardian: kGuardian, textField: "")
                            .background(GeometryGetter(rect: $kGuardian.rects[4]).foregroundColor(.clear))
    
                        RoundedButton().padding(.top, 20)
                    }
                    .padding(.top, 20)
                    .listRowInsets(EdgeInsets())
                    .offset(y: kGuardian.slide).animation(Animation.linear(duration: 0.3))
                }
                .navigationBarTitle(Text("New Restaurant"), displayMode: .inline)
                .navigationBarItems(trailing:
                    Button(action: {
    
                    }, label: {
                        Text("Cancel")
                    })
                )
            }
        }
    }
    
    struct RoundedButton: View {
        var body: some View {
            Button(action: {}) {
                HStack {
                    Spacer()
                    Text("Save")
                        .font(.headline)
                        .foregroundColor(.white)
                    Spacer()
                }
            }
            .padding(.vertical, 10.0)
            .background(Color.red)
            .cornerRadius(4.0)
            .padding(.horizontal, 50)
        }
    }
    

    添加以下代码,这些代码是吸收其父视图的大小和位置的视图。

    struct GeometryGetter: View {
        @Binding var rect: CGRect
    
        var body: some View {
            GeometryReader { geometry in
                Group { () -> ShapeView<Rectangle, Color> in
                    DispatchQueue.main.async {
                        self.rect = geometry.frame(in: .global)
                    }
    
                    return Rectangle().fill(Color.clear) as! ShapeView<Rectangle, Color>
                }
            }
        }
    }
    

    然后为键盘隐藏/显示通知添加以下代码。

    final class KeyboardGuardian: ObservableObject {
    
        let objectWillChange = PassthroughSubject<Void, Never>()
    
        public var rects: Array<CGRect>
        public var keyboardRect: CGRect = CGRect()
    
        // keyboardWillShow notification may be posted repeatedly,
        // this flag makes sure we only act once per keyboard appearance
        public var keyboardIsHidden = true
    
        public var slide: CGFloat = 0 {
            didSet {
                objectWillChange.send()
            }
        }
    
        public var showField: Int = 0 {
            didSet {
                updateSlide()
            }
        }
    
        init(textFieldCount: Int) {
            self.rects = Array<CGRect>(repeating: CGRect(), count: textFieldCount)
    
            NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(keyBoardDidHide(notification:)), name: UIResponder.keyboardDidHideNotification, object: nil)
        }
    
        deinit {
            NotificationCenter.default.removeObserver(self)
        }
    
        @objc func keyBoardWillShow(notification: Notification) {
            if keyboardIsHidden {
                keyboardIsHidden = false
                if let rect = notification.userInfo?["UIKeyboardFrameEndUserInfoKey"] as? CGRect {
                    keyboardRect = rect
                    updateSlide()
                }
            }
        }
    
        @objc func keyBoardDidHide(notification: Notification) {
            keyboardIsHidden = true
            updateSlide()
        }
    
        func updateSlide() {
            if keyboardIsHidden {
                slide = 0
            } else {
                let tfRect = self.rects[self.showField]
                let diff = keyboardRect.minY - tfRect.maxY
                print("tfRect", tfRect, "\nself.showField", self.showField)
                if diff > 0 {
                    slide += diff
                } else {
                    slide += min(diff, 0)
                }
            }
        }
    }
    

    【讨论】:

    • 我已经通过了参考,我在列表中使用动态文本字段而不是在表单中。请检查。
    • @RaviB,如果可能,分享演示应用程序。
    • 好的,我去看看。
    • 看起来ShapeView 已被弃用。这应该更新以反映当前的文档。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多