SwiftUI 列表中的键盘侦听器 [英] Keyboard Listener in List in SwiftUI

查看:57
本文介绍了SwiftUI 列表中的键盘侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have the list which contains a form of 5 Textfields, One Image & One button. Following is the ref from AppCoda. The issue I am facing here is I cannot show the last textfield when the keyboard is up. Found many relevant answers, but none of them is helpful. Also, I want to remove the animation from the list when clicked or long pressed.

视频在这里

任何帮助将不胜感激!

推荐答案

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

I have checkout link which you have added in question. Blaaahhhh, very irritating due to some syntax has been changed. Anyways, I'm not going to explain whole tutorial that you already have done.

我参考了这里: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 如下:

Update code in ContentView to initialise LabelTextField as follow:

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)
    }
}

添加以下代码,它们是吸收其父视图的大小和位置的视图.

Add following code which are view that absorbs the size and position of its parent view.

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>
            }
        }
    }
}

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

Then add following code for keyboard hide/show notification.

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)
            }
        }
    }
}

这篇关于SwiftUI 列表中的键盘侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆