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.
attributedText
sin especificar la fuente, el color y la alineación del texto conduce a la configuración de los valores predeterminados de los atributos NSAttributedString para textView. En mi caso, causa obtener diferentes alturas de la vista de texto para el mismo texto.Hay una nueva función para reemplazar sizeWithFont, que está delimitandoRectWithSize.
Agregué la siguiente función a mi proyecto, que hace uso de la nueva función en iOS7 y la anterior en iOS inferior a 7. Tiene básicamente la misma sintaxis que sizeWithFont:
Puede agregar ese IOS_NEWER_OR_EQUAL_TO_7 en su archivo prefix.pch en su proyecto como:
fuente
Si está utilizando UITableViewAutomaticDimension, tengo una solución realmente simple (solo iOS 8). En mi caso, es una vista de tabla estática, pero supongo que podría adaptar esto para prototipos dinámicos ...
Tengo una salida de restricción para la altura de la vista de texto y he implementado los siguientes métodos como este:
Pero recuerde : la vista de texto debe ser desplazable y debe configurar sus restricciones de modo que funcionen para la dimensión automática:
El ejemplo de celda más básico es:
fuente
La respuesta de Tim Bodeit es genial. Usé el código de Simple Solution para obtener correctamente la altura de la vista de texto, y utilicé esa altura
heightForRowAtIndexPath
. Pero no uso el resto de la respuesta para cambiar el tamaño de la vista de texto. En cambio, escribo código para cambiar laframe
vista de texto encellForRowAtIndexPath
.Todo funciona en iOS 6 y versiones anteriores, pero en iOS 7 el texto en la vista de texto no se puede mostrar completamente aunque la
frame
vista de texto se haya redimensionado. (No estoy usandoAuto Layout
). Debería ser la razón por la que en iOS 7 existeTextKit
y la posición del texto está controlada porNSTextContainer
inUITextView
. Entonces, en mi caso, necesito agregar una línea para configurarlasomeTextView
para que funcione correctamente en iOS 7.Como dice la documentación, lo que hace esa propiedad es:
Si lo deja con el valor predeterminado, después de cambiar el tamaño
frame
desomeTextView
, el tamaño detextContainer
no cambia, lo que lleva al resultado de que el texto solo se puede mostrar en el área antes de cambiar el tamaño.Y tal vez sea necesario configurarlo
scrollEnabled = NO
en caso de que haya más de unotextContainer
, para que el texto se refluya de unotextContainer
a otro.fuente
Aquí hay una solución más que apunta a la simplicidad y la creación rápida de prototipos :
Preparar:
UITextView
con otros contenidos.TableCell.h
.UITableView
está asociado conTableViewController.h
.Solución:
(1) Añadir a
TableViewController.m
:(2) Agregar a
TableCell.m
:Explicación:
Entonces, lo que está sucediendo aquí es esto: cada vista de texto está vinculada a la altura de las celdas de la tabla mediante restricciones verticales y horizontales; eso significa que cuando la altura de la celda de la tabla aumenta, la vista de texto también aumenta su tamaño. Usé una versión modificada del código de @ manecosta para calcular la altura requerida de una vista de texto para ajustar el texto dado en una celda. Eso significa que dado un texto con X número de caracteres,
frameForText:
devolverá un tamaño que tendrá una propiedadsize.height
que coincida con la altura requerida de la vista de texto.Ahora, todo lo que queda es actualizar la altura de la celda para que coincida con la altura de la vista de texto requerida. Y esto se logra en
heightForRowAtIndexPath:
. Como se señaló en los comentarios, dadosize.height
que solo es la altura de la vista de texto y no la celda completa, debería agregarse algún desplazamiento. En el caso del ejemplo, este valor fue 80.fuente
dream.dream
era el texto que estaba renderizando en la vista de texto.Un enfoque si está utilizando autolayout es dejar que el motor de autolayout calcule el tamaño por usted. Este no es el enfoque más eficiente, pero es bastante conveniente (y posiblemente el más preciso). Se vuelve más conveniente a medida que crece la complejidad del diseño de la celda, por ejemplo, de repente tiene dos o más vistas de texto / campos en la celda.
Respondí una pregunta similar con una muestra completa para dimensionar celdas de vista de tabla usando diseño automático, aquí:
¿Cómo cambiar el tamaño de la supervista para que se ajuste a todas las subvistas con autolayout?
fuente
La solución suave completa es la siguiente.
Primero, necesitamos la clase de celda con textView
Luego, lo usamos en TableViewController
Aquí
minLines
permite establecer la altura mínima para textView (para resistir la minimización de altura mediante AutoLayout con UITableViewAutomaticDimension).moveRowAtIndexPath:indexPath:
con el mismo indexPath comienza el nuevo cálculo y el nuevo diseño de la altura de tableViewCell.performWithoutAnimation:
elimina el efecto secundario (salto de desplazamiento de contenido de vista de tabla al comenzar una nueva línea mientras se escribe).Es importante preservar
relativeFrameOriginY
(contentOffsetY
¡ no !) Durante la actualizacióncontentSize
de la celda debido a las celdas antes de que la celda actual pueda cambiarse por cálculo automático de forma inesperada. Elimina los saltos visuales en la separación silábica del sistema al escribir palabras largas.Tenga en cuenta que no debe establecer la propiedad
estimatedRowHeight
! Lo siguiente no funcionaUtilice solo el método tableViewDelegate.
================================================== ========================
Si a uno no le importa la unión débil entre tableView y tableViewCell y la actualización de la geometría de tableView desde tableViewCell , es posible actualizar la
TextInputTableViewCell
clase anterior:fuente
La altura de su celda se calculará según el contenido de UILabel, pero TextField mostrará todo el texto.
fuente
Creo que de esta manera puede contar la altura de su vista de texto y luego cambiar el tamaño de su celda de vista de tabla de acuerdo con esa altura para que pueda mostrar el texto completo en la celda
fuente
Versión rápida
fuente
Si desea ajustar automáticamente
UITableViewCell
la altura en función de la altura de la altura interiorUITextView
. Vea mi respuesta aquí: https://stackoverflow.com/a/45890087/1245231La solución es bastante simple y debería funcionar desde iOS 7. Asegúrese de que la
Scrolling Enabled
opción esté desactivada en elUITextView
interiorUITableViewCell
del StoryBoard.Luego, en su UITableViewController viewDidLoad () establezca el
tableView.rowHeight = UITableViewAutomaticDimension
ytableView.estimatedRowHeight > 0
tales como:Eso es.
UITableViewCell
La altura se ajustará automáticamente en función de laUITextView
altura interior .fuente
Para iOS 8 y superior solo puedes usar
your_tablview.estimatedrowheight= minheight
usted quierefuente