【问题标题】:Avoiding Keyboard in SwifUI with TextEditor使用文本编辑器在 SwiftUI 中避免使用键盘
【发布时间】:2021-03-09 20:21:09
【问题描述】:

我正在尝试重新创建一个简单版本的 iOS 笔记应用程序。请注意,我是一个完整的 Swift 新手。我当前的问题是我希望我的视图在键盘出现时向上移动。我已经实现了一些 可以 执行此操作的代码,但它有一些令人讨厌的错误。它首先将视图向上移动得太高,然后当您开始输入时,视图就在它应该在的位置。这里有一些图片来表示,以及我的代码:

Before the keyboard appears

When the keyboard first appears

Once you begin typing

代码:

    class KeyboardResponder: ObservableObject {

    @Published var currentHeight: CGFloat = 0

    var _center: NotificationCenter
    
    @objc func keyBoardWillShow(notification: Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
                withAnimation {
                   currentHeight = keyboardSize.height
                    print("KEYBOARDSIZE.HEIGHT IN OBSERVER: \(keyboardSize.height)")
                }
            }
        print("KEYBOARD HEIGHT IN OBSERVER: \(currentHeight)")
        }
    @objc func keyBoardWillHide(notification: Notification) {
            withAnimation {
               currentHeight = 0
            }
        }

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

首先,有一个 KeyboardResponder 类,用于侦听键盘的出现和消失(带有一个已发布的高度变量)。

        VStack {
        
       TextEditor(text: $content).padding(.all).foregroundColor(fontColors[self.color]).font(fontStyles[self.font])

        HStack {
            Spacer()
            Button(action: {
                self.show = false
            }) {
                Text("Cancel").foregroundColor(.gray).font(.headline)
            }
            
            Spacer()
            
            Button(action: {
                self.showPanel = true
            }) {
                Image(systemName: "textformat").font(.headline).foregroundColor(.white).padding(.all)
            }.background(Color.green).clipShape(Circle())
            
            Spacer()
            
            Button(action: {
                self.show.toggle()
                self.saveData()
            }) {
                Text("Save").foregroundColor(Color(UIColor.systemBlue)).font(.headline)
            }
            Spacer()
        }
        
    }.padding(.bottom, keyboardResponder.currentHeight)

这是视图,照片中显示了编辑器。在这个视图的顶部,我有 @ObservedObject var keyboardResponder = KeyboardResponder()。我已经尝试过 .padding(.bottom,keyboardResponder.currentHeight) 以及 .offset(y: -keyboardResponder.currentHeight)。有谁知道怎么回事?

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    找到解决方案:

    我终于找到了一个可行的解决方案!我从 https://augmentedcode.io/2020/03/29/revealing-content-behind-keyboard-in-swiftui/

     fileprivate final class KeyboardObserver: ObservableObject {
        struct Info {
            let curve: UIView.AnimationCurve
            let duration: TimeInterval
            let endFrame: CGRect
        }
         
        private var observers = [NSObjectProtocol]()
         
        init() {
            let handler: (Notification) -> Void = { [weak self] notification in
                self?.keyboardInfo = Info(notification: notification)
            }
            let names: [Notification.Name] = [
                UIResponder.keyboardWillShowNotification,
                UIResponder.keyboardWillHideNotification,
                UIResponder.keyboardWillChangeFrameNotification
            ]
            observers = names.map({ name in
                NotificationCenter.default.addObserver(forName: name,
                                                       object: nil,
                                                       queue: .main,
                                                       using: handler)
            })
        }
     
        @Published var keyboardInfo = Info(curve: .linear, duration: 0, endFrame: .zero)
    }
     
    fileprivate extension KeyboardObserver.Info {
        init(notification: Notification) {
            guard let userInfo = notification.userInfo else { fatalError() }
            curve = {
                let rawValue = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! Int
                return UIView.AnimationCurve(rawValue: rawValue)!
            }()
            duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
            endFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
        }
    }
    
    
    struct KeyboardVisibility: ViewModifier {
        @ObservedObject fileprivate var keyboardObserver = KeyboardObserver()
     
        func body(content: Content) -> some View {
            GeometryReader { geometry in
                withAnimation() {
                    content.padding(.bottom, max(0, self.keyboardObserver.keyboardInfo.endFrame.height - geometry.safeAreaInsets.bottom))
                        .animation(Animation(keyboardInfo: self.keyboardObserver.keyboardInfo))
                }
            }
        }
    }
     
    fileprivate extension Animation {
        init(keyboardInfo: KeyboardObserver.Info) {
            switch keyboardInfo.curve {
            case .easeInOut:
                self = .easeInOut(duration: keyboardInfo.duration)
            case .easeIn:
                self = .easeIn(duration: keyboardInfo.duration)
            case .easeOut:
                self = .easeOut(duration: keyboardInfo.duration)
            case .linear:
                self = .linear(duration: keyboardInfo.duration)
            @unknown default:
                self = .easeInOut(duration: keyboardInfo.duration)
            }
        }
    }
    
    extension View {
        func keyboardVisibility() -> some View {
            return modifier(KeyboardVisibility())
        }
    }
    

    然后只需像这样.keyboardVisibility()

    将修饰符添加到要使用键盘向上移动的视图中

    【讨论】:

      【解决方案2】:

      在添加底部填充的VStack中添加这一行,导致vStack从安全区域中获取填充(键盘出现后键盘区域也属于安全区域)

      .edgesIgnoringSafeArea(.bottom)
      

      【讨论】:

      • 这最初是有效的,直到您开始输入,然后视图又向下移动。但是,我确实找到了解决方案!我会在上面的帖子中添加它。感谢您的回复!
      猜你喜欢
      • 2021-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-18
      • 1970-01-01
      • 2021-04-18
      相关资源
      最近更新 更多