2009-07-12 11 views
6

He estado preguntando a question o dos en los últimos días de trabajar en una aplicación que mantiene una barra de herramientas personalizada alineada con la parte superior del teclado del iPhone. Estoy usando el método descrito por Josh en this question; básicamente, tengo el controlador de vista para escuchar el UIKeyboardWillShowNotification y agregar la barra de herramientas según sea necesario.iPhone: ¿desplazar la celda de vista de tabla a la barra de herramientas alineada al teclado personalizada visible arriba?

El controlador de vista administra una vista de tabla cuyas celdas contienen un UITextField. El teclado y la barra de herramientas que se están presentando están editando estos campos de texto. El único problema que todavía tengo es esto: cuando el teclado y la barra de herramientas se presentan para una celda a más o menos la mitad de la tabla, se desplaza para ser visible sobre el teclado, pero no sobre la barra de herramientas.

Las celdas y los campos de texto todavía se pueden editar, pero aproximadamente la mitad de la celda está oculta debajo de la barra de herramientas. Si desaparezco de la barra de herramientas (no lo agregue al respondedor de notificaciones), la celda completa se vuelve visible, pero obviamente pierdo la funcionalidad que proporciona la barra de herramientas.

¿Hay alguna manera de cambiar la ubicación en la que se desplaza el campo de texto? He intentado jugar con el método UITableView scrollToRowAtIndexPath:atScrollPosition:animated:, pero tiende a dar resultados extraños al alternar entre varias celdas.

¿Cuál es el mejor método para desplazar una celda de vista de tabla a una posición visible encima de una barra de herramientas de teclado personalizada?

Respuesta

17

Hago exactamente lo que está describiendo en mi aplicación. Este es el código que uso, textualmente. Está muy bien animado, y parece funcionar maravillosamente.

dos negaciones:

  1. que pasan en parentView como parte de una inicialización personalizada.
  2. No escribí este código, no me estoy atribuyendo el mérito. Lo obtuve del realmente maravilloso blog de Matt Gallagher, Cocoa With Love.

static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3; 
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2; 
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8; 
// adjust this following value to account for the height of your toolbar, too 
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216; 


- (void)textFieldDidEndEditing:(UITextField *)textField 
{ 
    CGRect viewFrame = self.parentView.frame; 
    viewFrame.origin.y += animatedDistance; 

    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationBeginsFromCurrentState:YES]; 
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; 

    [self.parentView setFrame:viewFrame]; 

    [UIView commitAnimations]; 
} 

- (void) textFieldDidBeginEditing:(UITextField*) textField { 
    CGRect textFieldRect = [self.parentView.window convertRect:textField.bounds fromView:textField]; 
    CGRect viewRect = [self.parentView.window convertRect:self.parentView.bounds fromView:self.parentView]; 
    CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height; 
    CGFloat numerator = midline - viewRect.origin.y - MINIMUM_SCROLL_FRACTION * viewRect.size.height; 
    CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION) * viewRect.size.height; 
    CGFloat heightFraction = numerator/denominator; 

    if (heightFraction < 0.0) { 
    heightFraction = 0.0; 
    }else if (heightFraction > 1.0) { 
    heightFraction = 1.0; 
    } 

    animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction); 

    CGRect viewFrame = self.parentView.frame; 
    viewFrame.origin.y -= animatedDistance; 

    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationBeginsFromCurrentState:YES]; 
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; 

    [self.parentView setFrame:viewFrame]; 

    [UIView commitAnimations]; 
} 
+0

Supongo que se refiere a esta publicación de blog en http://cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html - La he visto también, y no Realmente tratamos con UITableViews, solo vistas estáticas con UITextFields. El problema con este enfoque es que laDistribución animada puede cambiar a medida que el usuario se desplaza por la vista de tabla. – Tim

+0

Lo estoy usando dentro de una UITableView sin problema alguno. – mmc

+0

Implementé esto, pero al inspeccionar más de cerca el código y los resultados, todo lo que hace es mover el origen de la vista de tabla fuera de la pantalla. Tiene el efecto descrito en la publicación del blog, pero hace que sea imposible para el usuario ver las primeras pocas celdas de la vista de tabla al editar una celda cerca de la parte inferior de la tabla. – Tim

0

Quizás podría cambiar el tamaño del UITableView para que sea el alto entre la barra de navegación y la barra de herramientas sobre el teclado, y luego deslice la fila hacia la vista?

+0

Lo probé - la vista de tabla parece cambiar el tamaño de OK, luego se ahoga bastante si intenta desplazar una celda que estaba en el área que se redimensionó a la pantalla. – Tim

0

Dado que todos los UITableView s son también UIScrollView s, puede llamar a todos los métodos de desplazamiento estándar en ellos.

Algo como esto va a hacer:

- (void)scrollTableView:(UITableView *)tableView toIndexPath:(NSIndexPath *)indexPath withBottomPadding:(CGFloat)bottomPadding 
{ 
    CGRect rectForRow = [tableView rectForRowAtIndexPath:indexPath]; 
    CGRect bounds = [tableView bounds]; 
    CGPoint contentOffset = [tableView contentSize]; 
    if (rectForRow.origin.y + rectForRow.size.height > contentOffset.y + bounds.size.height - bottomPadding) 
     [tableView setContentOffset:rectForRow.origin.y + rectForRow.size.height - bounds.size.height - bottomPadding animated:YES]; 
    else 
     [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES]; 
} 

Nota: No estoy en un Mac con Xcode en el momento.Voy a probar este código cuando estoy

6

Suponiendo que se conoce el NSIndexPath que le mostrará encima del teclado, puede utilizar el siguiente método rápido y limpio:

- (void)textFieldDidBeginEditing:(UITextField *)textField { 
    UITableViewCell *aCell = [myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:6 inSection:0]]; 
    CGSize cellSize = aCell.frame.size; 
    [myTableView setContentOffset:CGPointMake(0, cellSize.height*6) animated:YES]; 
}  

- (void)textFieldDidEndEditing:(UITextField *)textField { 
    [myTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] 
         atScrollPosition:UITableViewScrollPositionTop 
           animated:YES]; 
} 

Desde el UITableView hereda de UIScrollView Puede ajustar la propiedad contentOffset para reflejar la visibilidad de fila que le interesa.

En el método DidEndEditing, debe restaurar la posición de desplazamiento original. Esto se logra con un estándar scrollToRowAtIndexPath: atScrollPosition: llamada animada.

Cuestiones relacionadas