使用 swift 的 UITableView 中有 UITextField 时如何管理键盘?
How to manage keyboard when there are UITextFields in UITableView using swift?
我正在尝试找到一种方法来避免键盘不阻止动态 UITableView 中选定的 UITextField。
我知道这是一个常见问题,对此有很多答案。但是,我找到的答案要么在 Obj-C 中,要么不涉及动态 UITableView。
我的 table 视图有自己的 UITableViewCell,因此 UITextFields 已连接到它。
此外,我想在输入 UITextField 后刷新单元格。我可以将该信息(我猜是单元格的 IndexPath.row?)传递给 UIViewController 并让它监听更改并应用重新加载单元格方法?
这是我的相关代码:
class favCell: UITableViewCell, UITextFieldDelegate {
@IBOutlet weak var deciPadField: UITextField!
@objc func doneClicked(){
updateTotalWorth()
deciPadField.resignFirstResponder()
deciPadField.endEditing(true)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
deciPadField.becomeFirstResponder()
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentString: NSString = (textField.text ?? "") as NSString
let newString = currentString.replacingCharacters(in: range, with: string)
return newString.count <= 10
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
updateTotalWorth()
deciPadField.resignFirstResponder()
return true
}
private func textViewDidEndEditing(_ textView: UITextView) {
updateTotalWorth()
deciPadField.endEditing(true)
}
}
更新:
如果我可以从 UITableViewCell 访问我的 ViewControllers 视图,下面的代码就可以做到这一点:
func animateTextField(textField: UITextField, up: Bool) {
let movementDistance:CGFloat = -130
let movementDuration: Double = 0.3
var movement:CGFloat = 0
if up {
movement = movementDistance
} else {
movement = -movementDistance
}
UIView.beginAnimations("animateTextField", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration)
// Below line giving error, could not find the view. My ListVC.view should be referred to.
self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
UIView.commitAnimations()
}
func textFieldDidBeginEditing(textField: UITextField) {
self.animateTextField(textField: textField, up:true)
}
func textFieldDidEndEditing(textField: UITextField) {
self.animateTextField(textField: textField, up:false)
}
谢谢!
好吧,我终于想出了解决办法。我实现了这个答案:
这是解决的代码:
在 ViewController 的 ViewDidLoad 中添加了两个观察者,如下所示:
// Notification Observers
NotificationCenter.default.addObserver(self, selector: #selector(ListVC.keyboardWillShow(notification:)), name: Notification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ListVC.keyboardWillHide(notification:)), name: Notification.Name.UIKeyboardDidHide, object: nil)
并添加了相关的两个功能:
@objc func keyboardWillShow(notification: Notification) {
if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
}
}
@objc func keyboardWillHide(notification: Notification) {
UIView.animate(withDuration: 0.2, animations: {
// For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
})
}
在UITextFields连接的UITableViewCell中,简单实现UITextField Delegate,并在键盘将show/hide:
时添加相关的Notification.posts
deciPadField.delegate = self
func textFieldDidBeginEditing(_ textField: UITextField) {
NotificationCenter.default.post(name: Notification.Name.UIKeyboardDidShow, object: self)
}
func textFieldDidEndEditing(_ textField: UITextField) {
NotificationCenter.default.post(name: Notification.Name.UIKeyboardDidHide, object: self)
}
我有 inputAccessoryView,因此通过以下方式关闭键盘:
// Decipad config for adding Done button above itself
let toolBar = UIToolbar()
toolBar.sizeToFit()
let flexiableSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneClicked))
toolBar.setItems([flexiableSpace, doneButton], animated: false)
@objc func doneClicked(){
updateTotalWorth()
deciPadField.resignFirstResponder()
deciPadField.endEditing(true)
}
希望这对其他人有所帮助。
我正在尝试找到一种方法来避免键盘不阻止动态 UITableView 中选定的 UITextField。
我知道这是一个常见问题,对此有很多答案。但是,我找到的答案要么在 Obj-C 中,要么不涉及动态 UITableView。
我的 table 视图有自己的 UITableViewCell,因此 UITextFields 已连接到它。
此外,我想在输入 UITextField 后刷新单元格。我可以将该信息(我猜是单元格的 IndexPath.row?)传递给 UIViewController 并让它监听更改并应用重新加载单元格方法?
这是我的相关代码:
class favCell: UITableViewCell, UITextFieldDelegate {
@IBOutlet weak var deciPadField: UITextField!
@objc func doneClicked(){
updateTotalWorth()
deciPadField.resignFirstResponder()
deciPadField.endEditing(true)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
deciPadField.becomeFirstResponder()
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentString: NSString = (textField.text ?? "") as NSString
let newString = currentString.replacingCharacters(in: range, with: string)
return newString.count <= 10
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
updateTotalWorth()
deciPadField.resignFirstResponder()
return true
}
private func textViewDidEndEditing(_ textView: UITextView) {
updateTotalWorth()
deciPadField.endEditing(true)
}
}
更新:
如果我可以从 UITableViewCell 访问我的 ViewControllers 视图,下面的代码就可以做到这一点:
func animateTextField(textField: UITextField, up: Bool) {
let movementDistance:CGFloat = -130
let movementDuration: Double = 0.3
var movement:CGFloat = 0
if up {
movement = movementDistance
} else {
movement = -movementDistance
}
UIView.beginAnimations("animateTextField", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration)
// Below line giving error, could not find the view. My ListVC.view should be referred to.
self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
UIView.commitAnimations()
}
func textFieldDidBeginEditing(textField: UITextField) {
self.animateTextField(textField: textField, up:true)
}
func textFieldDidEndEditing(textField: UITextField) {
self.animateTextField(textField: textField, up:false)
}
谢谢!
好吧,我终于想出了解决办法。我实现了这个答案:
这是解决的代码:
在 ViewController 的 ViewDidLoad 中添加了两个观察者,如下所示:
// Notification Observers
NotificationCenter.default.addObserver(self, selector: #selector(ListVC.keyboardWillShow(notification:)), name: Notification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ListVC.keyboardWillHide(notification:)), name: Notification.Name.UIKeyboardDidHide, object: nil)
并添加了相关的两个功能:
@objc func keyboardWillShow(notification: Notification) {
if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
}
}
@objc func keyboardWillHide(notification: Notification) {
UIView.animate(withDuration: 0.2, animations: {
// For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
})
}
在UITextFields连接的UITableViewCell中,简单实现UITextField Delegate,并在键盘将show/hide:
时添加相关的Notification.postsdeciPadField.delegate = self
func textFieldDidBeginEditing(_ textField: UITextField) {
NotificationCenter.default.post(name: Notification.Name.UIKeyboardDidShow, object: self)
}
func textFieldDidEndEditing(_ textField: UITextField) {
NotificationCenter.default.post(name: Notification.Name.UIKeyboardDidHide, object: self)
}
我有 inputAccessoryView,因此通过以下方式关闭键盘:
// Decipad config for adding Done button above itself
let toolBar = UIToolbar()
toolBar.sizeToFit()
let flexiableSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneClicked))
toolBar.setItems([flexiableSpace, doneButton], animated: false)
@objc func doneClicked(){
updateTotalWorth()
deciPadField.resignFirstResponder()
deciPadField.endEditing(true)
}
希望这对其他人有所帮助。