我只是在选择了某个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,我不希望视图移动。
答案 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} }Š