2008-12-08 16 views
18

tengo un problema por el que cuando un textField se hace clic en un UITableViewCell, el método tableView:didSelectRowAtIndexPath: no consigue invocado. El problema es que necesito desplazar mi tableView a la posición correcta, de lo contrario, el teclado pasará directamente sobre el primer respondedor.UITextField en un UITableViewCell

tengo que luego mover código como este:

[[self tableView] scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; 

tanto en mi método delegado tableView y en mi método UITextField delegado, textFieldDidBeginEditing:.

¿Es la mejor manera de simplemente crear un nuevo método, pasarle el índice de la celda/campo de texto al que se hace clic, y llamar al método desde el delegado tableView y el delegado UITextField? mejor manera de hacerlo?

Respuesta

6

Puede configurar el controlador como el delegado de su UITextField, a continuación, ajustar la vista tabla, ya sea en textFieldDidBeginEditing: o textFieldShouldBeginEditing:

+0

Agosto, eso es lo que estoy haciendo actualmente. El problema con eso es que el desplazamiento debe suceder en dos lugares. En el método tableView: didSelectRowAtIndexPath: y en el método textFieldDidBeginEditing :. Al hacer clic directamente en el UITextField, no aparece, por lo que no se puede manejar en un solo lugar. – Coocoo4Cocoa

+0

Debería tener los métodos UITextFieldDelegate llamando al tableView: didSelectRowAtIndexPath: si el desplazamiento en ambos casos es el mismo. Esta es la única forma razonable de hacerlo, ya que UITableTexField oculta el UITableView. –

0

Registro de UIKeyboardWillShowNotification y UIKeyboardWillHideNotification, a continuación, ajustar la vista según sea necesario en los manejadores de notificación. Una de las aplicaciones de ejemplo muestra cómo hacerlo, pero olvido qué ... SQLiteBooks, o quizás EditableDetailView.

9

Hay un par de formas de solucionar este problema. Lo que sucede es que tableViewCell delega el evento táctil en sus subvistas, lo que hace que el campo de texto maneje el toque en lugar de su celda.

Para solucionar este:

  • conjunto de propiedades userinteractionEnabled del UITextField a NO, y luego cuando llegue el mensaje didSelectRowAtIndexPath que vuelva a activar userInteractionEnabled y llamar becomeFirstResponder del campo de texto. En v2.2 ni siquiera necesita establecer el indicador userInteractionEnabled, no lo he probado con otras versiones, sin embargo, la documentación es bastante clara de que debe tener esto habilitado. en el tableViewController sólo hay que han salvado la indexpath hasta que llegue el mensaje UIKeyboardDidShow

  • Crear un delegado para la UITextField que informa de nuevo a su tableViewController para que pueda ajustar el desfase de allí desplazamiento.

  • registro de los eventos de teclado y luego averiguar la scrolloffset comprobando lo que es el campo de texto en el modo de edición

0

he tenido problemas con este mismo tema, en el que tengo UITextFields interior de UITableViewCells y no podía obtener vista para desplazarse al campo cuando se estaba editando. El núcleo de mi solución está abajo.

La clave de este código es la línea donde se crea el UITextField. En lugar de codificar con dureza un valor xey en la función CGRectMake(), utiliza la xey de la celda en la que se coloca (+/- cualquier desplazamiento que desee desde los bordes de la celda, como se muestra a continuación). Los valores de codificación xey rígidos en UITextField * le dan a cada celda la misma posición de cuadro x, y para cada UITextField * (aparentemente es anulado por el recuadro de celdas cuando se muestra) así que cuando invocas el código 'scrollRectToVisible' no lo hace Parece que no tiene las coordenadas correctas a las que debería desplazarse.

1) crear células, y añadir UITextField * a la célula usando valores marco de X e Y de la célula (estoy incluyendo las compensaciones aquí, que son opcionales

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    UITableViewCell* cell; 
    cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"]; 
    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"UITableViewCell"] autorelease]; 

    //this is the critical part: make sure your UITextField* frame is based on the frame of the cell in which it's being placed. 
    UITextField* txtField = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+20, cell.frame.origin.y+9, 280, 31)]; 
    txtField.delegate = self; 

    [cell addSubview:txtField]; 
    return cell; 
} 

2) Ajustar Vista de desplazamiento en textFieldDidBeginEditing

-(void) textFieldDidBeginEditing:(UITextField *)textField { 

    CGRect textFieldRect = [textField frame]; 
    [self.tableView scrollRectToVisible:textFieldRect animated:YES]; 
} 
+0

A menos que me falta algo, esto simplemente se desplaza a la parte superior de la tabla cada vez que selecciona una celda.Además, las entradas anteriores desaparecen si te desplazas fuera de ellas. – cannyboy

3

No encontré ninguna solución que me funcione en la web. Después de días de buscar en Google y experimentar, finalmente tengo este publicado bien clavado. Es un error complejo en Apple iPhone como verá al final de esta publicación.

Si ejecutó en un tema como yo de la siguiente manera:

  1. tener tableviewcell mayor que la mitad de la pantalla del iPhone (No confundir con ejemplos de UICatalog de Apple tienen una corta tableview de células de menos de 50 puntos, aquí no aplicable.),

  2. tienen más de un uitexfields en la célula o combinación de UITextField y UITextView o UIWebView en la célula,

  3. Tapping entre uitextfields y UITextView o uiweb ver resultados en una posición de desplazamiento impredecible, el uitextfield cliqueado salta de la vista o queda cubierto por el teclado. Solo funciona la primera vez cuando el teclado aparece en la mesa de visión y no funciona bien posteriormente.

tuve la gran ruptura a través de mensajes después de leer similares a éste: http://alanduncan.net/old/index.php?q=node/13 No consiguieron completamente correcto tampoco. El dolor es causado por un error en los eventos de UIKeyboard. Cuando aparece el teclado por primera vez, emite un UIKeyboardWillShowNotification y UIKeybaordDidShowNotification. Theree es un error en iPhone que de alguna manera el primer UIKeyboardWillShowNotification difiere del UIKeyboardWillShowNotification posterior. La solución es OBSERVAR UIKeyboardDidShowNotification. Por eso, cuando aparecerá su celular, añada el siguiente código

NSNotificationCenter*nc=[NSNotificationCenter defaultCenter]; 
    [nc addObserver:self selectorselector(keyboardDidShow name:UIKeyboardDidShowNotification object:self.window]; 

En la función keyboardDidShow, tenemos que desplazar la tableView, no el tableviewcell como se sugiere en el post anterior. O puede ver varios objetos que se separan, no se desplazan juntos en una sola pieza.

(void)keyboardDidShow:(NSNotification *)notif 
{ 
    //1. see which field is calling the keyboard 
    CGRect frame; 
    if([textField_no1 isFirstResponder]) 
    frame=textField_no1.frame; 
    else if([textField_no2 isFirstResponder]) 
    frame=textField_no2.frame; 
    else if([textField_no3 isFirstResponder]) 
    frame=textField_no3.frame; 
    else if([textView isFirstResponder]) 
    frame=textView.frame; 
    else return; 
    CGRect rect=self.superview.frame; 

    //2. figure out how many pixles to scroll up or down to the posistion set by theKeyBoardShowUpHorizon. 

    //remove the complexity when the tableview has an offset 
    [((UITableView*)[self.superview).setContentOffset:CGPointMake(0,0) animated:YES]; 

    int pixelsToMove=rect.origin.y+ frame.origin.y-theKeyBoardShowUpHorizon; 

    //3. move the uitableview, not uitableviewcell 
    [self moveViewUpOrDownByPixels:pixelsToMove]; 

} 

- (void)moveViewUpOrDownByPixels:(int)pixels 
{ 

    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.6]; 

    //find the position of the UITableView, the superView of this tableview cell. 
    CGRect rect=self.superview.frame; 

    //moves tableview up (when pixels >0) or down (when pixels <0) 
    rect.origin.y -= pixels; 
    rect.size.height += pixels; 
    self.superview.frame = rect; 
    [UIView commitAnimations]; 
} 

para restaurar el tableView atrás, es necesario agregar observador UIKeyboardDidHideNotification (no UIKeyboardWillHideNotification según lo sugerido por otros puestos, para evitar el parpadeo) donde tableviewcell aparece cada vez y volver a poner la tableview a donde estaba.

[nc addObserver:self selectorselector(keyboarDidHide) name:UIKeyboardDidHideNotification object:nil]; 

- (void)keyboardDidHideNSNotification*)notif 
{ 
    //we have moved the tableview by number of pixels reflected in (self.superview.frame.origin.y). We need to move it back 
    [self moveViewUpOrDownByPixels:self.superview.frame.origin.y]; 
} 

No se olvide de eliminar tanto de la observesr cuando su celular desaparecer por [[NSNotificationCenter defaultCenter] removeObserver: ...

Eso es todo lo que necesita. Espero que un día el equipo de Apple iPhone resuelva este problema, tal vez en 4.0 en unos pocos meses.

3

He encontrado una solución.

  1. Abra el archivo .xib en el constructor de la interfaz.
  2. Seleccione la vista de tabla
  3. De IB menú seleccione Herramientas> Tamaño inspector El desplazamiento Ver tamaño de la sección, modifique Inserción -> valor inferior a 100, 150, 250 dependiendo de qué tan grande es su vista de tabla.

Código

-(void) textFieldDidBeginEditing:(UITextField *)textField 
{ 
    UITableViewCell *cell = (UITableViewCell *) [[textField superview] superview]; 
    [self.tableView scrollToRowAtIndexPath:[tableView indexPathForCell:cell] 
    atScrollPosition:UITableViewScrollPositionBottom animated:YES]; 
} 
3

descubrí que en realidad es bastante fácil de hacer esto.

El UITextField método delegado textFieldDidBeginEditing le dará el campo de texto, que luego se puede asignar a un indexPath usando:

self.currentIndexPath = [self.tableView indexPathForRowAtPoint:textField.frame.origin]; 

A continuación, puede desplazarse a la celda a la vista (es decir, en su UIKeyboardDidShowNotification controlador de notificación teclado) :

[self.tableView scrollToRowAtIndexPath:self.currentIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES]; 
+0

En este ejemplo, el marco del textField mostraría el origen en las coordenadas de la vista de contenido de la celda. Para que esto funcione, al menos para las tablas dinámicas, el punto necesario sería 'textField.superview.superview.frame.origin', que se traduce en: textField-> CellContentView-> Origen de la celda dentro de las coordenadas de la tabla. – Gobot

+0

(cont.) ... Lo cual es un poco hacky. – Gobot

21

encontré así las siguientes obras (se supone que usted está en un controlador de vista de tabla)

- (void)textFieldDidBeginEditing:(UITextField *)textField{ 
    CGPoint pnt = [self.tableView convertPoint:textField.bounds.origin fromView:textField]; 
    NSIndexPath* path = [self.tableView indexPathForRowAtPoint:pnt]; 
    [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES]; 
} 
+0

esto funcionó para mí, gracias! La parte engañosa fue usar convertPoint para obtener los orígenes de los puntos en la referencia correcta. – Hisham

+1

Awesome suggestion. – Gobot

1

didSelectRowAtIndexPath no se llamará para las celdas incrustadas UITextField; por lo tanto, la lógica de desplazamiento necesita estar en otro lugar.

- (void)textFieldDidBeginEditing:(UITextField *)textField { 
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1]; 
    UITableViewCell *cell = [_tableView cellForRowAtIndexPath:indexPath]; 
    [_tableView setContentOffset:CGPointMake(0, cell.frame.size.height) animated:YES]; 
} 

Asegúrese de delegado textField alambre a la libre

0

El problema se agrava por el hecho de que no existe una forma sencilla de averiguar si el usuario dio un golpecito en el campo de texto o se activa a través de becomeFirstResponder.

La solución más elegante que se me ocurrió fue implementar una subclase de celda hitTest:withEvent: y, básicamente, pretender que el campo de texto no existe hasta que se selecciona la celda.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    UIView *view = [super hitTest:point withEvent:event]; 

    if(view == self.textField && !self.selected) { 
     return self; 
    } 

    return view; 
} 

tableView:didSelectRowAtIndexPath: entonces debe hacer manualmente campo de texto de un primer nivel de respuesta.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    TextFieldCell* cell = [self.tableView cellForRowAtIndexPath:indexPath]; 

    [cell.textField becomeFirstResponder] 

    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; 
} 

Finalmente, debemos anular la selección de la fila cuando terminemos de editar. Esto se puede hacer a través del delegado UITextField o mediante notificación por teclado, lo que prefiera.

- (void)textFieldDidEndEditing:(UITextField *)textField { 
    [self.view endEditing:YES]; 
} 
Cuestiones relacionadas