logo caracteristicas ios ios4

ios - caracteristicas - Desplace UITextField sobre el teclado en un UITableViewCell en un UIViewController regular



ios 5 logo (10)

En swift4 podemos crear una extensión de UIViewController .

extension UIViewController { //MARK: Keyboard user interactions func handleContainerViewFrameOnKeyboardShowHide(originalContainerFrame: CGRect) { NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: OperationQueue.main) {(notification) in var info = (notification as NSNotification).userInfo! let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue var tableViewFrame = originalContainerFrame tableViewFrame.size.height = originalContainerFrame.size.height - keyboardFrame.size.height self.view.frame = tableViewFrame } NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: OperationQueue.main) { (notification) in self.view.frame = originalContainerFrame } } }

He intentado la mayoría de los ejemplos aquí en StackOverflow. También utilicé Apple. El problema que parece que tengo con ellos es que no tienen en cuenta que UITextField está en un UITableView. He hecho esto muchas veces, pero no de esta manera. Tengo un UITableViewCell personalizado con un UITextField en él.

En mi UITableView (que NO es un UITableViewController), necesito poder evitar ocultar el UITextField bajo la UITableView.

Tengo esto a partir de ahora:

-(void)viewDidLoad { .... [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; .... } - (void)scrollToRectOfTextField { UITableViewCell *cell = (UITableViewCell*)[self.activeTextField superview]; CGRect r = CGRectMake(self.activeTextField.frame.origin.x, cell.frame.origin.y+self.activeTextField.frame.origin.y, self.activeTextField.frame.size.width, self.activeTextField.frame.size.height); [self.tableView scrollRectToVisible:r animated:YES]; } - (void)keyboardDidShow:(NSNotification *)notification { if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone) { NSDictionary *userInfo = [notification userInfo]; CGSize size = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; NSLog(@"TableView: %@", NSStringFromCGRect(self.tableView.frame)); CGRect newTableViewFrame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.tableView.frame.size.height - size.height); self.tableView.frame = newTableViewFrame; NSLog(@"New TableView: %@", NSStringFromCGRect(self.tableView.frame)); self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height-size.height); } } - (void)keyboardWillHide:(NSNotification *)notification { NSDictionary *userInfo = [notification userInfo]; CGSize size = [[userInfo objectForKey: UIKeyboardFrameEndUserInfoKey] CGRectValue].size; self.tableView.frame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.tableView.frame.size.height + size.height); NSLog(@"%@", NSStringFromCGRect(self.tableView.frame)); } -(void)textFieldDidBeginEditing { [self scrollToRectOfTextField]; }

Esto parece empujar un montón de espacio en blanco más allá de mi teclado. Tenga en cuenta que también tengo un inputAccessoryView en mi UITextField también.

Ah, y no puedo usar ninguna clase de terceros. Me encanta TPKeyboardAvoidingScrollView, pero no puedo usar nada de terceros.


Esta respuesta es para usuarios de Xamarin iOS, sin embargo, alguien puede modificarla fácilmente para que funcione con Swift o Objective C.

La solución es muy simple y ha funcionado perfectamente en mi caso, donde necesitaba que apareciera una celda en la mitad superior de la pantalla para que el campo de texto de la celda estuviera por encima del teclado. Así que lo que hice es lo siguiente:

Implementé textField.ShouldBeginEditing de la siguiente manera:

myTextField.ShouldBeginEditing = textField => { myTableView.ScrollToRow(indexPath, UITableViewScrollPosition.Top, true); return true; };

Dónde:

myTextField es el campo de texto de la celda,

myTableView es la vista de tabla,

indexPath es la ruta del índice de la celda dentro de la vista de tabla.

Como mencioné anteriormente, esta solución funciona perfectamente en mi caso, así que pensé que podría compartirla con ustedes en caso de que también les funcione. Feliz codificacion :)


Gracias a @Salman por el enlace.
Simplemente observe que el ejemplo de Apple se utiliza para scrollview en la vista normal.
En la vista de tabla, debe convertir Point y Rect de activeField en la coordenada de la tabla, así que cambio algunas líneas en la función keyboardWasShown:

func keyboardWasShown(aNotification: NSNotification) { let info = aNotification.userInfo as! [String: AnyObject], kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue().size, contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0) self.tableBasket.contentInset = contentInsets self.tableBasket.scrollIndicatorInsets = contentInsets var aRect = self.view.frame aRect.size.height -= kbSize.height let pointInTable = activeField!.superview!.convertPoint(activeField!.frame.origin, toView: tableView) let rectInTable = activeField!.superview!.convertRect(activeField!.frame, toView: tableView) if !CGRectContainsPoint(aRect, pointInTable) { self.tableView.scrollRectToVisible(rectInTable, animated: true) } }

Y si su vista tiene tabBarController, recuerde restablecer contentInsets con tabBar height en lugar de UIEdgeInsetsZero (de lo contrario, sus últimas filas inferiores pueden estar ocultas bajo tabBar):

func keyboardWillBeHidden(aNotification: NSNotification) { //UIEdgeInsetsZero is used in view without tabBar //let contentInsets = UIEdgeInsetsZero let tabBarHeight = self.tabBarController!.tabBar.frame.height let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: tabBarHeight, right: 0) self.tableView.contentInset = contentInsets self.tableView.scrollIndicatorInsets = contentInsets } }


Hice una mezcla con las respuestas de Matt y también de Salman . Esto funciona para muchos campos de texto en un tableView. Swift 3

Básicamente es obtener el punto BOTTOM Y del textInput tocado. Una vez que tengamos eso, verifico si el teclado cubre el textInput y si lo hago cambiaría el contentOffset de la tableView

Primer registro a las notificaciones. En el init, si es un UIView o en viewDidLoad si es un UIViewController:

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

A continuación, configure el campo de texto tocado como entrada actual

var inputActive: UITextField! func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { inputActive = textInput return true }

Finalmente implementar el método de notificaciones:

func keyboardWillShow(notification: NSNotification) { var userInfo = notification.userInfo! if let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { // Get my height size let myheight = tableView.frame.height // Get the top Y point where the keyboard will finish on the view let keyboardEndPoint = myheight - keyboardFrame.height // Get the the bottom Y point of the textInput and transform it to the currentView coordinates. if let pointInTable = inputActive.superview?.convert(inputActive.frame.origin, to: tableView) { let textFieldBottomPoint = pointInTable.y + inputActive.frame.size.height + 20 // Finally check if the keyboard will cover the textInput if keyboardEndPoint <= textFieldBottomPoint { tableView.contentOffset.y = textFieldBottomPoint - keyboardEndPoint } else { tableView.contentOffset.y = 0 } } } } func keyboardWillHide(notification: NSNotification) { tableView.contentOffset.y = 0 }

Pocas cosas para agregar. El relleno es una distancia extra que añado en mi caso fue de 20 puntos. También en mi caso, el UITableView se agregó a un UIViewController pero esto debería funcionar también en un UITableViewController

¡Espero que esto ayude!


Hice una mezcla entre la respuesta de @Victor y algunos códigos que tenía. Creé una extensión práctica que se puede usar en muchos UITextField.

1.- Primero necesitamos una extensión para que UITextField administre las notificaciones del teclado.

extension UITextField { func keepTextFieldAboveKeyboard(tableView:UITableView) { var willShowNotification: NSObjectProtocol? var willHideNotification: NSObjectProtocol? willShowNotification = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: OperationQueue.main) {(notification) in var userInfo = notification.userInfo! if let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { // Get my height size let myheight = tableView.frame.height // Get the top Y point where the keyboard will finish on the view let keyboardEndPoint = myheight - keyboardFrame.height // Get the the bottom Y point of the textInput and transform it to the currentView coordinates. if let pointInTable = self.superview?.convert(self.frame.origin, to: tableView) { let textFieldBottomPoint = pointInTable.y + self.frame.size.height + 20 // Finally check if the keyboard will cover the textInput if keyboardEndPoint <= textFieldBottomPoint { tableView.contentOffset.y = textFieldBottomPoint - keyboardEndPoint } else { tableView.contentOffset.y = 0 } } } NotificationCenter.default.removeObserver(willShowNotification!) } willHideNotification = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: OperationQueue.main) { (notification) in tableView.contentOffset.y = 0 NotificationCenter.default.removeObserver(willHideNotification!) } } }

2.- Esta extensión anterior debe llamarse dentro de textFieldShouldBeginEditing para que podamos tener una extensión para eso también.

extension UITextField : UITextFieldDelegate { public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { guard let tableView = textField.parentView(of: UITableView.self) else { return true }; textField.keepTextFieldAboveKeyboard(tableView:tableView); return true; } }

3.- Finalmente, como se observa en el método anterior, necesitamos el TableView donde se encuentra la celda con el UITextField. Entonces podemos usar esta extensión (que también es útil para otros propósitos)

extension UIView { func parentView<T: UIView>(of type: T.Type) -> T? { guard let view = self.superview else { return nil } return (view as? T) ?? view.parentView(of: T.self) } }

4.- Finalmente, en la celda donde se encuentra el UITextField , simplemente escribimos esta simple línea de código

textField.delegate = textField;

Completamente reutilizable y universal.


Mi solución (funcionó en Xcode 8.3.3, Swift 3, iOS 10.3.1):

class MyTableViewController: UITableViewController { override func viewWillAppear(_ animated: Bool) { NotificationCenter.default.addObserver(self, selector: #selector(actionKeyboardDidShow(with:)), name: .UIKeyboardDidShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(actionKeyboardWillHide(with:)), name: .UIKeyboardWillHide, object: nil) } override func viewDidDisappear(_ animated: Bool) { NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil) NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil) } @objc private func actionKeyboardDidShow(with notification: Notification) { guard let userInfo = notification.userInfo as? [String: AnyObject], let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return } var contentInset = self.tableView.contentInset contentInset.bottom += keyboardFrame.height self.tableView.contentInset = contentInset self.tableView.scrollIndicatorInsets = contentInset } @objc private func actionKeyboardWillHide(with notification: Notification) { guard let userInfo = notification.userInfo as? [String: AnyObject], let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return } var contentInset = self.tableView.contentInset contentInset.bottom -= keyboardFrame.height self.tableView.contentInset = contentInset self.tableView.scrollIndicatorInsets = contentInset } }


Pasé todo el día tratando de resolver esto. Lo publiqué aquí, luego encontré un enlace de blog y una solución increíblemente simple. Se parece a esto:

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField { CGPoint pointInTable = [textField.superview convertPoint:textField.frame.origin toView:self.tableView]; CGPoint contentOffset = self.tableView.contentOffset; contentOffset.y = (pointInTable.y - textField.inputAccessoryView.frame.size.height); NSLog(@"contentOffset is: %@", NSStringFromCGPoint(contentOffset)); [self.tableView setContentOffset:contentOffset animated:YES]; return YES; } -(BOOL)textFieldShouldEndEditing:(UITextField *)textField { [textField resignFirstResponder]; if ([textField.superview.superview isKindOfClass:[UITableViewCell class]]) { UITableViewCell *cell = (UITableViewCell*)textField.superview.superview; NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:TRUE]; } return YES; }

Comprueba esto para iOS 8


Probé el enlace que @inturbidus publicó para iOS8 pero desafortunadamente no funcionó para mí. Después de un poco de investigación, resulta que Apple tiene un código de muestra en su sitio web para que esto funcione de manera natural como lo hacen en el UITableViewController. Aquí está el enlace de Apple para la versión de Objective-C y también estoy agregando la versión rápida aquí.

Enlace Objective-C de Apple (Desplácese hasta el listado 5-1): https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

Rápida adaptación de la versión Objective-C.

var activeField: UITextField? func textFieldDidBeginEditing(textField: UITextField) { self.activeField = textField } func textFieldDidEndEditing(textField: UITextField) { self.activeField = nil } func registerForKeyboardNotifications() { NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil) } func keyboardWasShown(aNotification: NSNotification) { let info = aNotification.userInfo as! [String: AnyObject], kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue().size, contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0) self.tableView.contentInset = contentInsets self.tableView.scrollIndicatorInsets = contentInsets // If active text field is hidden by keyboard, scroll it so it''s visible // Your app might not need or want this behavior. var aRect = self.view.frame aRect.size.height -= kbSize.height if !CGRectContainsPoint(aRect, activeField!.frame.origin) { self.tableView.scrollRectToVisible(activeField!.frame, animated: true) } } func keyboardWillBeHidden(aNotification: NSNotification) { let contentInsets = UIEdgeInsetsZero self.tableView.contentInset = contentInsets self.tableView.scrollIndicatorInsets = contentInsets }


de actualizada a 4.2. Funciona en iOS 12.0.

Swift 4.2

override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow(with:)), name: UIResponder.keyboardDidShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(with:)), name: UIResponder.keyboardWillHideNotification, object: nil) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidShowNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) } @objc func keyboardDidShow(with notification: Notification) { guard let userInfo = notification.userInfo as? [String: AnyObject], let keyboardFrame = (userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return } var contentInset = self.tableView.contentInset contentInset.bottom += keyboardFrame.height tableView.contentInset = contentInset tableView.scrollIndicatorInsets = contentInset } @objc func keyboardWillHide(with notification: Notification) { guard let userInfo = notification.userInfo as? [String: AnyObject], let keyboardFrame = (userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return } var contentInset = self.tableView.contentInset contentInset.bottom -= keyboardFrame.height tableView.contentInset = contentInset tableView.scrollIndicatorInsets = contentInset }


Desplace UITextField sobre el teclado en un UITableViewCell en un UIViewController swift 3 y Xcode 8.1

1) establecer Delegado = UITextFieldDelegate

override func viewWillAppear(_ animated: Bool) { NotificationCenter.default.addObserver(self, selector: #selector(DayViewController.keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil); NotificationCenter.default.addObserver(self, selector: #selector(DayViewController.keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil); } func textFieldDidBeginEditing(_ textField: UITextField) { self.activeField = textField } func textFieldDidEndEditing(_ textField: UITextField) { self.activeField = nil } //MARK: - Keyboard Show and Hide Methods func keyboardWillShow(notification: NSNotification) { let info = notification.userInfo! as! [String: AnyObject], kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue.size, contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0) self.FourthTblMainTableView.contentInset = contentInsets self.FourthTblMainTableView.scrollIndicatorInsets = contentInsets var aRect = self.FourthTblMainTableView.frame aRect.size.height -= kbSize.height } func keyboardWillHide(notification: NSNotification) { let contentInsets = UIEdgeInsets.zero self.FourthTblMainTableView.contentInset = contentInsets self.FourthTblMainTableView.scrollIndicatorInsets = contentInsets }