En primer lugar, es muy importante tener en cuenta que existe una gran diferencia entre UITextView y UILabel cuando se trata de cómo se representa el texto. UITextView no solo tiene inserciones en todos los bordes, sino que también el diseño del texto es ligeramente diferente.
Por lo tanto, sizeWithFont:
es una mala manera de ir a UITextViews.
En UITextView
su lugar , tiene una función llamada sizeThatFits:
que devolverá el tamaño más pequeño necesario para mostrar todos los contenidos del UITextView
interior de un cuadro delimitador, que puede especificar.
Lo siguiente funcionará igualmente para iOS 7 y versiones anteriores y, a partir de ahora, no incluye ningún método que esté en desuso.
Solución simple
- (CGFloat)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width {
UITextView *calculationView = [[UITextView alloc] init];
[calculationView setAttributedText:text];
CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return size.height;
}
Esta función tomará NSAttributedString
ay el ancho deseado como a CGFloat
y devolverá la altura necesaria
Solución detallada
Como recientemente hice algo similar, pensé que también compartiría algunas soluciones a los Problemas conectados que encontré. Espero que ayude a alguien.
Esto es mucho más profundo y cubrirá lo siguiente:
- Por supuesto: establecer la altura de un en
UITableViewCell
función del tamaño necesario para mostrar el contenido completo de un contenidoUITextView
- Responda a los cambios de texto (y anime los cambios de altura de la fila)
- Mantener el cursor dentro del área visible y mantener el primer respondedor
UITextView
al cambiar el tamaño UITableViewCell
mientras se edita
Si está trabajando con una vista de tabla estática o solo tiene un número conocido de UITextView
s, puede hacer que el paso 2 sea mucho más simple.
1. Primero, sobrescriba la heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// check here, if it is one of the cells, that needs to be resized
// to the size of the contained UITextView
if ( )
return [self textViewHeightForRowAtIndexPath:indexPath];
else
// return your normal height here:
return 100.0;
}
2. Defina la función que calculó la altura necesaria:
Agregue un NSMutableDictionary
(en este ejemplo llamado textViews
) como una variable de instancia a su UITableViewController
subclase.
Use este diccionario para almacenar referencias al individuo de la siguiente UITextViews
manera:
(y sí, indexPaths son claves válidas para los diccionarios )
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Do you cell configuring ...
[textViews setObject:cell.textView forKey:indexPath];
[cell.textView setDelegate: self]; // Needed for step 3
return cell;
}
Esta función ahora calculará la altura real:
- (CGFloat)textViewHeightForRowAtIndexPath: (NSIndexPath*)indexPath {
UITextView *calculationView = [textViews objectForKey: indexPath];
CGFloat textViewWidth = calculationView.frame.size.width;
if (!calculationView.attributedText) {
// This will be needed on load, when the text view is not inited yet
calculationView = [[UITextView alloc] init];
calculationView.attributedText = // get the text from your datasource add attributes and insert here
textViewWidth = 290.0; // Insert the width of your UITextViews or include calculations to set it accordingly
}
CGSize size = [calculationView sizeThatFits:CGSizeMake(textViewWidth, FLT_MAX)];
return size.height;
}
3. Habilite el cambio de tamaño mientras edita
Para las siguientes dos funciones, es importante que el delegado de la UITextViews
se establezca en su UITableViewController
. Si necesita algo más como delegado, puede solucionarlo haciendo las llamadas relevantes desde allí o utilizando los enlaces apropiados de NSNotificationCenter.
- (void)textViewDidChange:(UITextView *)textView {
[self.tableView beginUpdates]; // This will cause an animated update of
[self.tableView endUpdates]; // the height of your UITableViewCell
// If the UITextView is not automatically resized (e.g. through autolayout
// constraints), resize it here
[self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor
}
4. Siga el cursor mientras edita
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToCursorForTextView:textView];
}
Esto hará que el UITableView
desplazamiento a la posición del cursor, si no está dentro del Rect visible de UITableView:
- (void)scrollToCursorForTextView: (UITextView*)textView {
CGRect cursorRect = [textView caretRectForPosition:textView.selectedTextRange.start];
cursorRect = [self.tableView convertRect:cursorRect fromView:textView];
if (![self rectVisible:cursorRect]) {
cursorRect.size.height += 8; // To add some space underneath the cursor
[self.tableView scrollRectToVisible:cursorRect animated:YES];
}
}
5. Ajuste el rectángulo visible, colocando insertos
Durante la edición, partes del suyo UITableView
pueden estar cubiertas por el teclado. Si las inserciones de las vistas de tabla no están ajustadas, scrollToCursorForTextView:
no podrá desplazarse hasta el cursor, si está en la parte inferior de la vista de tabla.
- (void)keyboardWillShow:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, kbSize.height, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
}
- (void)keyboardWillHide:(NSNotification*)aNotification {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.35];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, 0.0, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
[UIView commitAnimations];
}
Y última parte:
Dentro de su vista se cargó, regístrese para las notificaciones de cambios de teclado a través de NSNotificationCenter
:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
Por favor, no te enojes conmigo, por hacer esta respuesta tanto tiempo. Si bien no todo es necesario para responder la pregunta, creo que hay otras personas a quienes estos temas directamente relacionados serán útiles.
ACTUALIZAR:
Como señaló Dave Haupert, olvidé incluir la rectVisible
función:
- (BOOL)rectVisible: (CGRect)rect {
CGRect visibleRect;
visibleRect.origin = self.tableView.contentOffset;
visibleRect.origin.y += self.tableView.contentInset.top;
visibleRect.size = self.tableView.bounds.size;
visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
return CGRectContainsRect(visibleRect, rect);
}
También noté que scrollToCursorForTextView:
todavía incluía una referencia directa a uno de los TextFields en mi proyecto. Si tiene un problema con bodyTextView
no ser encontrado, verifique la versión actualizada de la función.