[英]Dismiss Keyboard when Touching Sibling
Despite all the "Dismissing Keyboard" questions, there doesn't appear to be one referring to this specific scenario. 尽管存在所有“关闭键盘”问题,但似乎没有人提到此特定方案。
I am working on a ViewController with the following (simplified) hierarchy: 我正在使用以下(简化)层次结构的ViewController:
The ViewController is loaded from an XIB as are the two PLCustomView's. 像两个PLCustomView一样,从XIB加载ViewController。 I can't seem to get the view to
endEditing
(dismiss the keyboard) when the user selects anything contained by the UIStackViews. 当用户选择UIStackViews包含的任何内容时,我似乎看
endEditing
的视图(关闭键盘)。
Adding a gesture recognizer to the view certainly will work; 在视图中添加手势识别器当然可以; however, this requires that every view in the hierarchy gets the gesture recognizer added to it, which doesn't seem very scalable.
但是,这要求层次结构中的每个视图都必须添加手势识别器,而手势识别器的扩展性似乎并不高。 There are actually quite a few subviews on the real version of this.
实际上,此版本的实际版本中有很多子视图。
I have tried adding the dismissal in touchesBegan
to the UIView subclass of each of the custom views, but this only dismisses the keyboard if the user touches the view which is containing the firstResponder. 我尝试将
touchesBegan
的解雇添加到每个自定义视图的UIView子类中,但这仅在用户触摸包含firstResponder的视图时才解雇键盘。 For example, if the textField in PLCustomViewOne
is active then touching anywhere else in that view dismisses the keyboard, but touching outside it, say, PLCustomViewTwo
, does not. 例如,如果
PLCustomViewOne
的textField处于活动状态,则触摸该视图中的其他任何位置都会关闭键盘,但是触摸外部的键盘(例如PLCustomViewTwo
)则不会。
In your view controller class, create outlets to your two custom views (via ctrl-drag from storyboard) 在视图控制器类中,为两个自定义视图创建出口(通过情节提要中的ctrl拖动)
@IBOutlet weak var customViewOne: PLCustomViewOne!
@IBOutlet weak var customViewTwo: PLCustomViewTwo!
From these, you should be able to access your UITextField instances, say by 通过这些,您应该能够访问UITextField实例,例如
customViewOne.textField
customViewTwo.textField
(Preferably if you make this property non-private in your custom class). (最好是在自定义类中将此属性设置为非私有)。 Also (in you view controller class) create a private
UITextField
property to hold the (possibly) current (/most recently used) text field. 同样(在您的视图控制器类中)创建一个私有的
UITextField
属性,以保存(可能)当前(/最近使用)的文本字段。
private var currentTextField: UITextField?
Overload the viewDidLoad
method of your UIViewController
subclass to initialize the delegates for the two "public" text field instances 重载
UIViewController
子类的viewDidLoad
方法以初始化两个“公共”文本字段实例的委托
override func viewDidLoad() {
super.viewDidLoad()
// Handle the user input in the text fields through delegate callbacks (and set tags)
customViewOne.textField.delegate = self
customViewOne.textField.delegate = self
}
Moreover, use the two textFieldShouldReturn(...)
and textFieldDidBeginEditing(...)
methods of the UITextFieldDelegate
to resign the (active) text fields status's as first responder and to update the currentTextField
reference, respectively. 此外,使用
UITextFieldDelegate
的两个textFieldShouldReturn(...)
和textFieldDidBeginEditing(...)
方法分别将(活动)文本字段的状态声明为第一响应者,并更新currentTextField
引用。
// UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool {
// User finished typing (hit return): hide the keyboard.
textField.resignFirstResponder()
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
currentTextField = textField
}
Finally (also in view controller class), resign any possibly current text field as first responder, in case any of your two buttons is pressed in-middle-of editing/or when touchesBegan in any of the UIView 最后(也在视图控制器类),任何辞职可能当前文本字段作为第一响应,在任何情况下的两个按钮被按下编辑在-中等的/或当的touchesBegan在任何的UIView
... user does action/tap/gesture elsewhere {
if let currentTextField = currentTextField {
currentTextField.resignFirstResponder()
}
}
The key here is that you keep track of which text field is first responder (by currentTextField
property in view controller), and resign just this text field. 这里的关键是您跟踪哪个文本字段是第一个响应者(通过视图控制器中的
currentTextField
属性),然后仅对此文本字段进行签名。
I was able to achieve the desired result by adding the following to the custom views: 通过将以下内容添加到自定义视图中,我能够实现所需的结果:
private func addTapToResignFirstResponder () {
let action = UITapGestureRecognizer(target: self, action: Selector("dismissFirstResponder"))
self.view.addGestureRecognizer(action)
}
func dismissFirstResponder () {
UIApplication.sharedApplication().sendAction("resignFirstResponder", to:nil, from:nil, forEvent:nil)
}
where addTapToResignFirstResponder()
is called in the UIView
's initialization. 在
UIView
的初始化中调用addTapToResignFirstResponder()
地方。
This globally dismisses the first responder regardless of where it is without needing a reference. 这样,无论在哪里,都可以将第一响应者解雇,而无需参考。
dismissFirstResponder()
can also be overridden in subclasses for additional flexibility. 还可以在子类中覆盖
dismissFirstResponder()
以获得更多的灵活性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.