Deshabilitar el desplazamiento automático de UITableView al editar UITextField dentro de UITableViewCell

estoy usando personalizado UITableViewCellestá dentro de mi UITableView. Cada uno de estos UITableViewCells es bastante alto y contiene un UITextField en la parte superior de la aplicación.

Cuando un usuario toca el UITextField para editarlo aparece un teclado y el UITableView se desplaza automáticamente para que la celda esté en la parte superior de la pantalla.

El problema es que esto desplaza el UITableView al fondo de la UITableViewCell, no la parte superior. Cuando el UITableViewCell es alto y editado el UITextField está en la parte superior para que no puedas ver el UITextField. Sé cómo desplazar el UITableView programáticamente, pero simplemente no sé cómo deshabilitar este desplazamiento automático para poder desplazar el UITableView por mi cuenta. ¿Cómo puedo hacer esto?

preguntado el 09 de marzo de 12 a las 15:03

¿Te das cuenta de esto? Corriendo hacia el mismo problema. -

@SteveBaughman, ¿ha encontrado una solución? -

no :( en realidad dejé de usar la vista de tabla por esta y otras razones ... :/ -

Definitivamente es un problema con los comportamientos automáticos de UITableViewController. -

9 Respuestas

El comportamiento de desplazamiento automático se encuentra en el UITableViewController funcionalidad

Para deshabilitar el desplazamiento automático encontré dos formas:

  1. Utilizar en lugar de la UITableViewController simplemente un UIViewController - configure la fuente de datos y delegue por su cuenta.
  2. Anular el viewWillAppear método y no llamar [super viewWillAppear: animated]

Con ambas soluciones, no solo deshabilita el Autoscroll, sino también algunas otras características agradables pero no esenciales, que se describen en la descripción general de la referencia de clase de Apple:

https://developer.apple.com/documentation/uikit/uitableviewcontroller

Respondido el 29 de junio de 17 a las 15:06

Tuve el mismo problema y la solución 2 funcionó. He probado esto en iOS 5.0.0 y versiones posteriores y se mantiene hasta ahora (la versión actual es 6.1.2). No puedo garantizarlo en 4, pero bueno, es 2013, por lo que probablemente podamos decir que 5.0 es el sistema operativo más bajo admitido en este momento. - Cocoadelica

El problema con esto es que las inserciones no están adaptadas para acomodar el teclado, al menos no en iOS 7.0.6. Esto significa que se necesitará más código para hacer esto a mano: captura de notificaciones de teclado, ... Feo. - el significado importa

No puedo creer que no supiera sobre esto hasta hoy... Estaba teniendo problemas con TPKeyboardAvoiding... ¡Gracias! - fidel lopez

El punto no2 funciona en 9.1. Buena respuesta @Dominic. Gracias - pkc456

Nunca anularía viewWillAppear: sin llamar a super. UITableViewController subclases UIViewController, y Apple "requiere" que todas las subclases UIViewController llamen a super. Desde el Documentación de UIViewController: "Si anula este método, debe llamar a super en algún momento de su implementación". - ryanipete

Defina propiedades para su UITableViewController:

@property (nonatomic) BOOL scrollDisabled;
@property (nonatomic) CGFloat lastContentOffsetY;

Antes de llamar becomeFirstResponder:

// Save the table view's y content offset 
lastContentOffsetY = tableViewController.tableView.contentOffset.y;
// Enable scrollDisabled
scrollDisabled = YES;

Agregue el siguiente código a su controlador de vista de tabla:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (self.scrollDisabled) {
        [self.tableView setContentOffset:CGPointMake(0, lastContentOffsetY)];
    }
    ...
}

Después de llamar resignFirstResponderestablecer scrollDisabled = NO.

respondido 01 nov., 16:19

Este no es un problema de vista de desplazamiento, es una clase tableViewController. La respuesta correcta fue anular viewWilAppear - sofía swicz

Puede hacer lo siguiente:

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardDidShow:)
                                                 name:UIKeyboardDidShowNotification object:nil];
}

- (void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification
{
    self.tableView.scrollEnabled = NO;
}

- (void)keyboardDidShow:(NSNotification *)notification
{
    double delayInSeconds = 0.3;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            self.tableView.scrollEnabled = YES;
    });
}

Luego implemente este método UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (! self.tableView.scrollEnabled)
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}

!!! Pero tenga cuidado, si el usuario toca una ubicación en el UITextField que será cubierta por el teclado, entonces no se desplazará.

Desde mi punto de vista, lo mejor que puede hacer es asegurarse de que todas las celdas desde la parte superior hasta la siguiente con el UITextField incluido, estarán visibles cuando se muestre el teclado.

Respondido 12 Abr '13, 14:04

-scrollViewDidScroll: de hecho, se llama cuando ocurre el desplazamiento automático, esta es la mejor solución: Nikolái Spassov

La mejor manera es subclasificar UITableView y luego anular setContentOffset(_ contentOffset: CGPoint, animated: Bool) y no llamar super.setContentOffset(_ contentOffset: CGPoint, animated: Bool). En este método es donde el controlador de vista está haciendo el desplazamiento automático.

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
{
    //Do nothing
}

Respondido el 15 de diciembre de 16 a las 17:12

Esta fue la respuesta correcta para mí para UITableView con UITextView en las celdas. - olle lind

Puede deshabilitar el ajuste de inserción de contenido automático de esta manera:

tableView.contentInsetAdjustmentBehavior = .never

Respondido el 22 de enero de 20 a las 12:01

Esto no funcionará ya que el teclado oscurecerá las celdas debajo de él. - Félix Marianayagam

El problema para mí no fue tanto que se desplazara sino que quitó la vista de texto que se estaba editando de la pantalla.

Entonces, en lugar de evitar el desplazamiento, simplemente vuelvo a desplazar la vista de la tabla a donde quiero cuando se activa la edición, así:

public func textViewShouldBeginEditing(textView: UITextView) -> Bool {            
  dispatch_async(dispatch_get_main_queue()) {
    tableViewController.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
  }
  return true
}

Respondido 27 Feb 15, 22:02

Desafortunadamente, anular -viewWillAppear: no funciona para mí en iOS 8.

Aquí está mi solución (como en la implementación de UITableViewController):

- (void)viewDidLoad {

[super viewDidLoad];

[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillShowNotification object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillHideNotification object:nil];
}

Dado que el comportamiento de desplazamiento automático es invocado por las notificaciones de mostrar/ocultar de UIKeyboard, simplemente NO las observe.

Respondido 03 Abr '15, 09:04

¿Esto sigue funcionando para ti? No puedo hacerlo funcionar en iOS 11 / Xcode 9 - Simonthumper

¿Intentó establecer "scrollsToTop" - propiedad de tableview en NO. Por defecto es SÍ.

respondido 10 mar '12, 16:03

lo intenté todavía, pero no funcionó... scrollToTop no maneja esto... ¡gracias por la respuesta de todos modos! - barbilla_animal

Puedes intentar hacer lo siguiente:

self.tableView.scrollEnabled = NO;

Esto debería deshabilitar la vista de desplazamiento en la vista de tabla.

Respondido el 24 de diciembre de 12 a las 01:12

Esto no impide el desplazamiento automático que hace UITableViewController al tocar un campo de texto dentro de UITableViewCell. Gujamín

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.