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

时间:2019-08-31 16:52:26

标签: swiftui

在以下帮助下,我得以跟随键盘显示屏上的按钮。 但是,动画不能很好地应用。

How to show complete List when keyboard is showing up in 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

1 个答案:

答案 0 :(得分:2)

您的主要问题是您正在使用隐式动画。这不仅可能会使您不想动画的事物动起来,而且也永远不要在容器上应用.animation()。在SwiftUI文档中的一些警告中,这是其中之一:

  

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

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

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

我还用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))
    }
}