为啥我根据键盘高度调整视图的功能表现不正常?

Posted

技术标签:

【中文标题】为啥我根据键盘高度调整视图的功能表现不正常?【英文标题】:Why does my function to adjust view according to keyboard height behave erratically?为什么我根据键盘高度调整视图的功能表现不正常? 【发布时间】:2020-02-20 05:24:16 【问题描述】:

我正在尝试重新创建一个 Facebook 注册页面以供练习;我的 viewController 的设置如下: 1)顶部的个人资料图像容器, 2)电子邮件文本字段 3)密码文本字段 4)确认密码文本框

为了解决键盘阻止“确认密码”字段的问题,我使用了如下监听器。

问题在于,当用户第一次单击文本字段进行输入时(无论是哪个),屏幕向上移动得太远,以至于顶部的电子邮件文本字段最终超出了屏幕大小最佳。但是,当我关闭键盘并重新单击任何文本字段时,它会按预期上升:直到顶部文本字段到达屏幕顶部。

我找不到这种行为的其他原因,即使在我重新编写了一些代码后它仍然存在。

我的 ViewController 设置:

class ViewController: UIViewController 


@objc func dismissKeyboard() 
        view.endEditing(true)


let imageContainer: UIView = 
   let v = UIView()
    v.translatesAutoresizingMaskIntoConstraints = false
    v.backgroundColor = .red
    return v
()

let emailTF: UITextField = 
   let tf = UITextField()
    tf.translatesAutoresizingMaskIntoConstraints = false
    tf.placeholder = "EMAIL"
    return tf
()

let passwordTF: UITextField = 
   let tf = UITextField()
    tf.translatesAutoresizingMaskIntoConstraints = false
    tf.placeholder = "Password"
    return tf
()


let confirmPasswordTF: UITextField = 
   let tf = UITextField()
    tf.translatesAutoresizingMaskIntoConstraints = false
    tf.placeholder = "Confirm password"
    return tf
()


@objc func keyboardWillShow(notification: NSNotification) 
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue 
        if self.view.frame.origin.y == 0 
            self.view.frame.origin.y -= keyboardSize.height
        
    


@objc func keyboardWillHide(notification: NSNotification) 
    if self.view.frame.origin.y != 0 
        self.view.frame.origin.y = 0
    


override func viewDidLoad() 
    super.viewDidLoad()
    view.backgroundColor = .lightGray

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
       NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)

    view.addSubview(imageContainer)
    view.addSubview(emailTF)
    view.addSubview(passwordTF)
    view.addSubview(confirmPasswordTF)

            NSLayoutConstraint.activate([

            imageContainer.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            imageContainer.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.275),
            imageContainer.widthAnchor.constraint(equalTo: view.heightAnchor),
            imageContainer.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),

            emailTF.topAnchor.constraint(equalTo: imageContainer.bottomAnchor),
            emailTF.heightAnchor.constraint(equalToConstant: 100),
            emailTF.widthAnchor.constraint(equalToConstant: 200),
            emailTF.centerXAnchor.constraint(equalTo: view.centerXAnchor),

            passwordTF.topAnchor.constraint(equalTo: emailTF.bottomAnchor, constant: 20),
            passwordTF.heightAnchor.constraint(equalToConstant: 100),
            passwordTF.widthAnchor.constraint(equalToConstant: 200),
            passwordTF.centerXAnchor.constraint(equalTo: view.centerXAnchor),

            confirmPasswordTF.topAnchor.constraint(equalTo: passwordTF.bottomAnchor, constant: 20),
            confirmPasswordTF.heightAnchor.constraint(equalToConstant: 100),
            confirmPasswordTF.widthAnchor.constraint(equalToConstant: 200),
            confirmPasswordTF.centerXAnchor.constraint(equalTo: view.centerXAnchor),

        ])

    let tapToDismissKeyboard: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard))
    view.addGestureRecognizer(tapToDismissKeyboard)

    



非常感谢您能帮助我解决这个问题。

【问题讨论】:

我建议你使用这个:github.com/hackiftekhar/IQKeyboardManager/tree/master/… 感谢您的建议,@chiragbhalara!我正在编写此应用程序以进行练习,因此目前不想依赖第三方库 希望我的回答能为您澄清事情:) 【参考方案1】:

似乎这是here 提出的一个已知问题以及其他 SO 问题..

需要说明的两点:-

1) 使用UIResponder.keyboardFrameEndUserInfoKey 代替UIResponder.keyboardFrameBeginUserInfoKey 在:

if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue 

keyboardWillShow()

2) 这样做,您将获得键盘的总高度包括工具栏。这意味着:

但是,当我关闭键盘并重新单击任何文本字段时,它 按预期上升:仅直到顶部文本字段到达顶部 屏幕。

这是错误的行为,您会得到不正确的高度,不包括工具栏和:

问题是用户第一次点击文本字段时 类型(无论哪一个),屏幕向上移动太远,这样 顶部的电子邮件文本字段最终超出了屏幕大小 顶。

这实际上是具有实际高度的预期行为。您可以计算工具栏的高度并从该高度减少它以实现您的目标!如果您的 VC 嵌入在导航控制器中,您可以使用 this

希望这会有所帮助。

【讨论】:

真的很抱歉,我忘了把答案标记为正确 没问题,乐于助人:)

以上是关于为啥我根据键盘高度调整视图的功能表现不正常?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AutoLayout 根据父高度调整子视图高度而不添加/删除约束

显示软键盘而不改变视图位置

如何使用自动布局根据子视图调整父视图的高度

UIWebView 内容高度不正确

使用固定大小的子视图和自动布局调整 UIView 的大小不起作用

动画期间键盘和文本视图之间的间隙