仅在选择了某个textField时才向上移动视图

时间:2017-01-28 14:52:32

标签: ios swift uitextfield

我只是在选择了某个textField时尝试移动我的视图。我得到了它,但是,如果我现在选择其他textField,它也会在其他textFields上再次激活,为什么?

像这样我正在处理移动:

func keyboardWillShow(notification: NSNotification) {

        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y == 0{
                self.view.frame.origin.y -= keyboardSize.height
            }
        }

    }

    func keyboardWillHide(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y != 0{
                self.view.frame.origin.y += keyboardSize.height
            }
        }
    }

就像这样,我在textField addObserver中尝试touchDown

@IBAction func didTapCertainTextField(_ sender: Any) {
        NotificationCenter.default.addObserver(self, selector: #selector(CreateCardViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

    }

流言:

假设我有5个textFields(1,2,3,4,5)

我将观察者添加到第三个textField。我先点击,视图不动,我点击第三个它移动,我再次点击1然后它移动。为什么?如果单击的textField为1,我不希望视图移动。

2 个答案:

答案 0 :(得分:0)

您正在寻找的是知道textField是否是第一响应者,但您正在做的是在显示键盘时收到通知。

我鼓励你研究这类可可: https://developer.apple.com/reference/uikit/uiresponder

或者你可以在你的精确cas中通过Xcode界面构建器将UITextField绑定动作绑定到EditingDidBegin和EditingDidEnd 或者以代理人的方式编程 https://developer.apple.com/reference/uikit/uitextfielddelegate

我也注意到你开始观察这个事件,但在我看来你永远不会停止观察它们。 为此,你应该在你的对象的生命时间结束之前的某个时刻调用removeObserver:name:object:

答案 1 :(得分:0)

如果我理解正确,那么只有在键盘隐藏UITextField时才会尝试移动视图。如果是这种情况,我专门为此写了以下扩展名:

extension UIViewController {

    func pushViewForTextFields() {
        // Push view according text field's position
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    @objc func keyboardWillShow(_ sender: Notification) {
        var currentEditingTextField: UITextField!
        let keyboardHeight =  UIScreen.main.bounds.maxY - ((sender as NSNotification).userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height

        // Find which text field is currently editing (O(n))
        for view in self.view.subviews as [UIView] {
            if let tf = view as? UITextField {
                if tf.isEditing {
                    currentEditingTextField = tf
                    break
                }
            }
        }

        if currentEditingTextField == nil || currentEditingTextField < 0 {
            // no textfield found
            return
        }

        // get absolute frame of the text field, regardless of its parent view
        let globalFrame = (currentEditingTextField.superview?.convert(senderObject.frame, to: self.view))!

        // the 30 below is completely arbitrary; change it to whatever you want to suit your needs. This is basically the distance you want between the top of the keyboard and the editing text field (30px)

        if globalFrame.maxY + 30 > keyboardHeight {
            self.view.frame.origin.y = -(globalFrame.maxY + 30 - keyboardHeight)
        }
        else {      // keyboard not covering the text field
            self.view.frame.origin.y = 0
        }

    }

    @objc func keyboardWillHide(_ sender: Notification) {
        // move view back to normal position when editing is done
        self.view.frame.origin.y = 0
    }

}

然后只需在您的UIViewController中使用它

override func viewDidLoad() {
    super.viewDidLoad()

    self.pushViewForTextFields()
}

请注意,只有当UITextField个对象位于主UIView的顶层时,此扩展才有效。即如果它们没有嵌入任何子视图中。如果子视图中有任何文本字段,那么你必须通过在那里嵌套另一个for循环来扩展for循环,以检查每个子视图中的每个视图(在这种情况下为O(n ^ 2))。 / p>

这可能不是最有效的方式(循环遍历UIView的树和所有),但我只是写了一个通用解决方案,我可以轻松地应用于我的{{1} }Š