如何使底部按钮跟随 SwiftUI 中的键盘显示 [英] How to make the bottom button follow the keyboard display in SwiftUI

查看:26
本文介绍了如何使底部按钮跟随 SwiftUI 中的键盘显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

With the help of the following, I was able to follow the button on the keyboard display. However, animation cannot be applied well.

如何显示完整列表当键盘出现在 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))
    }
}

在此处输入图片说明

推荐答案

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

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. Of the few warnings in SwiftUI's documentation, this is one of them:

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

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.

来源:https://developer.apple.com/documentation/swiftui/查看/3278508-动画

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

The modified code removes the implicit .animation() call and replaces it with two implicit withAnimation closures.

我还用 keyboardFrameEndUserInfoKey 替换了 keyboardFrameEndUserInfoKey,第二次调用给出了无用的几何体.

I also replaced keyboardFrameEndUserInfoKey with keyboardFrameEndUserInfoKey, second calls were giving useless geometry.

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

这篇关于如何使底部按钮跟随 SwiftUI 中的键盘显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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