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

Ika*_*Ika 2 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
    }
}
Run Code Online (Sandbox Code Playgroud)
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))
    }
}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

kon*_*iki 6

您的主要问题是您使用的是隐式动画。它不仅可以为您可能不想制作动画的东西制作动画,而且您永远不应该在容器上应用 .animation() 。在 SwiftUI 文档中的少数警告中,这是其中之一:

在叶视图而不是容器视图上使用此修饰符。动画适用于该视图中的所有子视图;在容器视图上调用 animation(_:) 会导致范围无限。

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

修改后的代码删除了隐式.animation()调用,并用两个隐式withAnimation闭包替换了它。

我也替换keyboardFrameEndUserInfoKeykeyboardFrameEndUserInfoKey,第二次调用给出了无用的几何图形。

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))
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @kontiki `keyboardAnimationCurveUserInfoKey` 的值为 7。显然,他们使用未记录的键盘动画曲线。我们可以使用原始值 7 来初始化未记录的“UIView.AnimationCurve”值,但该曲线只能在“UIKit”中使用,而不能在“SwiftUI”中使用。除非我遗漏了什么,否则目前不可能在“SwiftUI”中正确遵循键盘动画。 (2认同)