简体   繁体   English

如何使底部按钮跟随SwiftUI中的键盘显示

[英]How to make the bottom button follow the keyboard display in SwiftUI

With the help of the following, I was able to follow the button on the keyboard display. 在以下帮助下,我得以跟随键盘显示屏上的按钮。 However, animation cannot be applied well. 但是,动画不能很好地应用。

How to show complete List when keyboard is showing up in SwiftUI 在SwiftUI中显示键盘时如何显示完整列表

import SwiftUI
import Combine
import UIKit

class KeyboardResponder: ObservableObject {
    let willset = PassthroughSubject<CGFloat, Never>()
    private var _center: NotificationCenter
    @Published var currentHeight: CGFloat = 0
    var keyboardDuration: TimeInterval = 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)
    }

    deinit {
        _center.removeObserver(self)
    }

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

            guard let duration:TimeInterval = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
            keyboardDuration = duration
        }
    }

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

struct Content: View {
    @ObservedObject var keyboard = KeyboardResponder()

    var body: some View {
        VStack {
            Text("text")

            Spacer()

            NavigationLink(destination: SubContentView()) {
                Text("Done")
            }
        }
        .padding(.bottom, keyboard.currentHeight)
        animation(Animation.easeInOut(duration: keyboard.keyboardDuration))
    }
}

enter image description here 在此处输入图片说明

Your main problem, is that you are using an implicit animation. 您的主要问题是您正在使用隐式动画。 Not only it may be animating things you may not want to animate, but also, you should never apply .animation() on containers. 这不仅可能会使您不想动画的事物动起来,而且也永远不要在容器上应用.animation()。 Of the few warnings in SwiftUI's documentation, this is one of them: 在SwiftUI文档中的一些警告中,这是其中之一:

Use this modifier on leaf views rather than container views. 在叶子视图而不是容器视图上使用此修饰符。 The animation applies to all child views within this view; 动画适用于此视图中的所有子视图; calling animation(_:) on a container view can lead to unbounded scope. 在容器视图上调用animation(_ :)可能会导致无限范围。

Source: https://developer.apple.com/documentation/swiftui/view/3278508-animation 来源: https : //developer.apple.com/documentation/swiftui/view/3278508-animation

The modified code removes the implicit .animation() call and replaces it with two implicit withAnimation closures. 修改后的代码将删除隐式的.animation()调用,并将其替换为两个隐式的withAnimation闭包。

I also replaced keyboardFrameEndUserInfoKey with keyboardFrameEndUserInfoKey , second calls were giving useless geometry. 我还用keyboardFrameEndUserInfoKey替换了keyboardFrameEndUserInfoKey ,第二次调用给出了无用的几何形状。

class KeyboardResponder: ObservableObject {
    let willset = PassthroughSubject<CGFloat, Never>()
    private var _center: NotificationCenter
    @Published var currentHeight: CGFloat = 0
    var keyboardDuration: TimeInterval = 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)
    }

    deinit {
        _center.removeObserver(self)
    }

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

            guard let duration:TimeInterval = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
            keyboardDuration = duration

            withAnimation(.easeInOut(duration: duration)) {
                self.currentHeight = keyboardSize.height
            }

        }
    }

    @objc func keyBoardWillHide(notification: Notification) {
        guard let duration:TimeInterval = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }

        withAnimation(.easeInOut(duration: duration)) {
            currentHeight = 0
        }
    }
}


struct ContentView: View {
    @ObservedObject var keyboard = KeyboardResponder()

    var body: some View {

        return VStack {
            Text("text \(keyboard.currentHeight)")

            TextField("Enter text", text: .constant(""))
            Spacer()

            NavigationLink(destination: Text("SubContentView()")) {
                Text("Done")
            }
        }
        .padding(.bottom, keyboard.currentHeight)
//        .animation(Animation.easeInOut(duration: keyboard.keyboardDuration))
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM