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.
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:)])
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;
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;
Utilisez cette petite fonction
-(CGSize) getContentSize:(UITextView*) myTextView{
return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}
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);
}
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)
_textView.textContainerInset = UIEdgeInsetsZero;
_textView.textContainer.lineFragmentPadding = 0;
N'oubliez pas le lineFragmentPadding
@ 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.
solution simple - textView.isScrollEnabled = false
fonctionne parfaitement lorsque vous vous trouvez dans une autre vue de défilement ou une cellule tableView avec UITableViewAutomaticDimension