【问题标题】:How to keep UIButton back to its position after dismissing keyboard in iOS?在 iOS 中关闭键盘后如何让 UIButton 回到原来的位置?
【发布时间】:2021-11-17 22:08:27
【问题描述】:

我在屏幕底部有一个 UIButton,当用户在 UITextView 中键入时,该按钮会连接到键盘(输入附件视图),就像我附加的屏幕截图(紫色箭头标记)一样。现在,一旦关闭键盘,我希望此按钮位于屏幕底部,而不是输入附件视图(检查黄色箭头标记流)。

这是我使用的代码

override func viewDidLoad() {
    super.viewDidLoad()
    confirmButtonUI()
    subscribeToShowKeyboardNotifications()
    // Do any additional setup after loading the view.
 }



   func confirmButtonUI() {
        confirmButton.layer.cornerRadius = 20.0
        confirmButton.layer.shadowRadius = 1.0
        confirmButton.layer.shadowColor = UIColor(displayP3Red: 33/255, green: 68/255, blue: 27/255, alpha: 0.18).cgColor
        confirmButton.layer.backgroundColor = UIColor(displayP3Red: 164/255, green: 208/255, blue: 208/255, alpha: 1).cgColor
        confirmButton.isEnabled = false
        confirmButton.layer.shadowOffset = CGSize(width: 0.0, height: 2.0)
        confirmButton.layer.shadowOpacity = 1.0
        confirmButton.layer.masksToBounds = false
    }
    




   func subscribeToShowKeyboardNotifications() {

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

  }



 @objc func keyboardWillShow(_ notification: Notification) {
        let userInfo = notification.userInfo
        confirmButton.layer.cornerRadius = 0.0
        othersTextField.inputAccessoryView = confirmButton

        let keyboardSize = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue
        _ = keyboardSize.cgRectValue.height
        let animationDuration = userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
        UIView.animate(withDuration: animationDuration) {
            self.view.layoutIfNeeded()
        }
    }



@objc func keyboardWillHide(_ notification: Notification) {
        othersTextField.inputAccessoryView = nil
        confirmButtonBottomConstrains.constant = 57   //Crash here

        let userInfo = notification.userInfo
        let animationDuration = userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
        UIView.animate(withDuration: animationDuration) {
            self.view.layoutIfNeeded()
        }
    }

In this method its crashing on this line " confirmButtonBottomConstrains.constant = 57 "

我所做的是,一旦键盘关闭,我将 inputAccessoryView 设为 nil,然后尝试使用底部 nslayout 约束将按钮设置为 57(就像我在 UI 中设置的那样),但这条线因以下消息而崩溃

Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value 

请帮我解决这个问题

【问题讨论】:

  • 错误指出confirmButtonBottomConstrains 为空,这意味着您尚未分配/链接约束。查看是否已将约束链接到情节提要或是否以编程方式完成,查看是否正确设置了约束
  • 是的,我做到了,但我认为当我将按钮移动到 textview 的 inputaccessory 视图时,这个约束可能会消失
  • 现在可以用了吗?

标签: ios swift keyboard uibutton


【解决方案1】:

问题

您尚未提供有关视图是通过编程方式设置还是在情节提要中设置的详细信息。我假设它是一个故事板(因为我没有看到任何视图初始化)。

另外,我不确定您是如何将按钮粘贴为inputAccessoryView。我无法复制这种行为。在您的情况下,将已经是视图层次结构一部分的视图设置为辅助视图可能会导致移除现有约束的未记录行为。

解决方案

您可以非常轻松地创建一个按钮,而不是使用相同按钮,并将其作为inputAccessoryView分配给您的UITextField/UITextView

这将消除缺少约束的问题,因为原始视图永远不会改变。

它看起来像这样,(除了你的禁用按钮):

设置输入附件视图的代码:

override func viewDidLoad() {
    super.viewDidLoad()
    setupInputAccessory()
    othersTextField.delegate = self
}

func setupInputAccessory(){
    let width = UIScreen.main.bounds.width
    let frame = CGRect(x: 0, y: 0, width: width, height: 44.0)
    let btn = UIButton(frame: frame)
    
    btn.backgroundColor = UIColor.purple
    btn.setTitleColor(UIColor.white, for: .normal)
    btn.setTitle("Confirm", for: .normal)
    btn.addTarget(self, action: #selector(accessoryConfirmTapped), for: .touchUpInside)
    
    othersTextField.inputAccessoryView = btn
}

@objc func accessoryConfirmTapped(){
    othersTextField.resignFirstResponder()
}

注意事项

以上是您现有代码之外的代码sn-p。但是,通过这种方法,我从您的代码中删除了以下内容。

  1. 在键盘事件中更改othersTextField.inputAccessoryView
  2. 确认按钮底部约束。

但它的要点是,我有两个单独的按钮。一个由情节提要设置,另一个设置在代码中并附加到 TextField。我不与控制器的视图共享按钮并作为输入附件。

如果您想进一步检查,我在GitHub Repo 中有完整的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    相关资源
    最近更新 更多