Alternativa a iOS7 UITextView contentsize.height

78

Estoy portando una de las aplicaciones de iOS 6.1 a iOS 7. Estoy usando un diseño en el UITextViewque hay un ancho fijo, pero su altura se basa en su tamaño de contenido. Para iOS 6.1, verificar el tamaño del contenido.height y configurarlo como la altura del marco de la vista de texto fue suficiente, pero no funciona en iOS 7.

¿Cómo puedo crear una UITextViewcon un ancho fijo, pero una altura dinámica en función del texto que se muestra?

NOTA: Estoy creando estas vistas a partir del código, no con Interface Builder.

Zoltan Varadi
fuente

Respuestas:

180

Con este siguiente código, puede cambiar la altura de su UITextView dependiendo de un ancho fijo (funciona en iOS 7 y la versión anterior):

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width
{
    UITextView *textView = [[UITextView alloc] init];
    [textView setAttributedText:text];
    CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

Con esta función, tomará un NSAttributedString y un ancho fijo para devolver la altura necesaria.

Si desea calcular el marco a partir de un texto con una fuente específica, debe usar el siguiente código:

- (CGSize)text:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
    {
        CGRect frame = [text boundingRectWithSize:size
                                          options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                       attributes:@{NSFontAttributeName:font}
                                          context:nil];
        return frame.size;
    }
    else
    {
        return [text sizeWithFont:font constrainedToSize:size];
    }
}

Puede agregar eso SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TOen su archivo prefix.pch en su proyecto como:

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

También puede reemplazar la prueba anterior SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)por:

if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])‌
Jordan Montel
fuente
Solo puedo dártelo después de 24 horas. tenga paciencia, es suyo :)
Zoltan Varadi
16
¿Quizás debería vincular a las respuestas de las que las tomó? stackoverflow.com/questions/18368567/…
andrew-caulfield
@Jordan Montel, para otra pregunta, si tengo ancho y alto fijos, ¿cómo puedo encontrar el mejor tamaño de fuente para una cadena asignada? Tengo un problema similar en iOS7 (en iOS6, puedo hacer eso)
LiangWang
1
@Jacky: prueba y error; aumente o disminuya el tamaño en 1 hasta que su altura calculada sea demasiado grande. O hágalo de tamaño 1000 y ajuste el tamaño automáticamente.
Cœur
esta respuesta YA ES INCORRECTA. Intente ingresar mucho texto dentro de dicho campo de texto. ¿Tamaño repentinamente incorrecto? Al menos NSStringDrawingUsesFontLeadinges extra
user2159978
42

Esto funcionó para mí para iOS6 y 7:

CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
    self.myTextView.height = textViewSize.height;
Ana
fuente
Hola, Sí, me está entrando en acción ... Se usa "txtviewHeight.frame.size.height" en lugar de "txtviewHeight.contentSize.height"
Mani
¿Por qué obtengo la altura de la propiedad que no se encuentra en el objeto de tipo "UITextView"?
Hexark
@HexarktextView.bounds.size.height
usuario
21

En iOS7, se UITextViewutiliza NSLayoutManagerpara diseñar texto:

// If YES, then the layout manager may perform glyph generation and layout for a given portion of the text, without having glyphs or layout for preceding portions.  The default is NO.  Turning this setting on will significantly alter which portions of the text will have glyph generation or layout performed when a given generation-causing method is invoked.  It also gives significant performance benefits, especially for large documents.
@property(NS_NONATOMIC_IOSONLY) BOOL allowsNonContiguousLayout;

deshabilitar allowsNonContiguousLayoutpara arreglar contentSize:

textView.layoutManager.allowsNonContiguousLayout = NO;
estrella nueva
fuente
7
Su respuesta no se ajusta a la pregunta, pero se ajusta a mi problema. Así que voto a favor :)
vietstone
Esto no me soluciona el tamaño del contenido. El desplazamiento está desactivado.
Dvole
Esta pieza de código resolvió mi problema, pero ¿qué significa el método de generación de generación en su comentario?
Code Farmer
15

Usa esta pequeña función

-(CGSize) getContentSize:(UITextView*) myTextView{
    return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}
Blake Hamilton
fuente
Funciona en iOS6 e iOS7 para mí. ¡Gracias!
Paul Brady
4

Mi solución final se basa en HotJard, pero incluye inserciones superiores e inferiores del contenedor de texto en lugar de usar 2 * fabs (textView.contentInset.top):

- (CGFloat)textViewHeight:(UITextView *)textView
{
    return ceilf([textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height +
                 textView.textContainerInset.top +
                 textView.textContainerInset.bottom);
}
xZenon
fuente
3

Hay una solución más simple, usando este método:

+(void)adjustTextViewHeightToContent:(UITextView *)textView;
{
    if([[UIDevice currentDevice].systemVersion floatValue] >= 7.0f){
        textView.height = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height+2*fabs(textView.contentInset.top);
    }else{
        textView.height = textView.contentSize.height;
    }
}

UPD : funciona solo para mostrar texto (isEditable = NO)

HotJard
fuente
Parece que tu solición no funciona. Cuando el método textview goto segunda línea usedRectForTextContainerdevuelve la misma altura.
Valerii Pavlov
Oh, puede ser, solo lo
usaré
1
   _textView.textContainerInset = UIEdgeInsetsZero;
   _textView.textContainer.lineFragmentPadding = 0;

Simplemente no olvides el lineFragmentPadding

ChaoWang
fuente
0

solución simple: textView.isScrollEnabled = false funciona perfectamente cuando está dentro de otra vista de desplazamiento o celda de tableView conUITableViewAutomaticDimension

Kirow
fuente
0

@ Ana's, la solución de @Blake Hamilton en rápida .

var contentHeight: CGFloat = textView.sizeThatFits(textView.frame.size).height

Lo bueno para mí fue que esto también devuelve el correcto contentSize, cuando isScrollEnablese establece en falso. La configuración en falso devolvió el tamaño del marco de la vista de texto en lugar del tamaño del contenido.

Baran Emre
fuente