web-dev-qa-db-fra.com

iOS7 UITextView alternative contentsize.height

Je porte l'une des applications d'iOS 6.1 à iOS 7. J'utilise une disposition dans laquelle il existe une variable UITextView qui a une largeur fixe, mais sa hauteur dépend de la taille du contenu. Pour iOS 6.1, vérifier la taille du contenu et la définir comme hauteur du cadre de la vue texte suffisait, mais cela ne fonctionne pas sous iOS 7. 

Comment puis-je créer une UITextView avec une largeur fixe, mais une hauteur dynamique en fonction du texte affiché?

REMARQUE: je crée ces vues à partir de code, pas avec Interface Builder.

76
Zoltan Varadi

Avec ce code suivant, vous pouvez modifier la hauteur de votre UITextView en fonction d'une largeur fixe (cela fonctionne sur iOS 7 et la version précédente):

- (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;
}

Avec cette fonction, vous utiliserez une chaîne NSAttributedString et une largeur fixe pour renvoyer la hauteur requise.

Si vous souhaitez calculer le cadre à partir d'un texte avec une police spécifique, vous devez utiliser le code suivant:

- (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];
    }
}

Vous pouvez ajouter ce SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO à votre fichier prefix.pch dans votre projet en tant que:

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

Vous pouvez également remplacer le test précédent SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) par:

if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])‌
178
Jordan Montel

Cela a fonctionné pour moi pour iOS6 et 7:

CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
    self.myTextView.height = textViewSize.height;
42
Ana

Dans iOS7, UITextView utilise NSLayoutManager pour mettre en forme le texte:

// 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;

désactiver allowsNonContiguousLayout pour corriger contentSize:

textView.layoutManager.allowsNonContiguousLayout = NO;
20
nova

Utilisez cette petite fonction

-(CGSize) getContentSize:(UITextView*) myTextView{
    return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}
15
Blake Hamilton

Ma solution finale est basée sur HotJard, mais elle inclut les encarts supérieur et inférieur du conteneur de texte au lieu d'utiliser 2 * fabs (textView.contentInset.top):

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

Il existe une solution plus simple, en utilisant cette méthode: 

+(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: fonctionne uniquement pour l'affichage de texte (isEditable = NO)

2
HotJard
   _textView.textContainerInset = UIEdgeInsetsZero;
   _textView.textContainer.lineFragmentPadding = 0;

N'oubliez pas le lineFragmentPadding

1
ChaoWang

@ Ana's, la solution de @Blake Hamilton dans Swift

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

La bonne chose pour moi est que cela renvoie également la valeur correcte contentSize, lorsque isScrollEnable est défini sur false. La valeur false a renvoyé la taille du cadre de la vue de texte à la place de la taille du contenu. 

0
Bem

solution simple - textView.isScrollEnabled = false fonctionne parfaitement lorsque vous vous trouvez dans une autre vue de défilement ou une cellule tableView avec UITableViewAutomaticDimension

0
Kirill Serebriakov