[self.Review sizeToFit];
Résultat avant sizeToFit:
NSStringFromCGRect(self.Review.frame): {{90, 20}, {198, 63}}
Résultat après sizeToFit:
NSStringFromCGRect(self.Review.frame): {{90, 20}, {181, 45}}
Je veux que la largeur reste la même. Je veux juste changer la hauteur. Le masque automatique est
(lldb) po self.Review
(UILabel *) $1 = 0x08bb0fe0 <UILabel: 0x8bb0fe0; frame = (90 20; 181 45); text = 'I'm at Mal Taman Anggrek ...'; clipsToBounds = YES; opaque = NO; autoresize = LM+RM+H; userInteractionEnabled = NO; layer = <CALayer: 0x8bb68b0>>
Je sais qu'il existe un moyen de le faire avec: Comment ajuster et faire la largeur d'un UILabel pour s'adapter à la taille du texte?
Les réponses sont soit étranges (nous devons réapprovisionner les informations de police). Ou pas clair.
Vous devrez également définir une largeur maximale et indiquer à votre programme quoi faire si sizeToFit vous donne une largeur supérieure à ce maximum.
J'utiliserai l'étrange solution d'utiliser sizeWithFont
. C'est étrange car UILabel connaît déjà la police de l'étiquette.
En fait, comment se comporte sizeToFit de toute façon? Comment décide-t-on si nous avons besoin d'un UILabel plus fin ou plus grand?
Voilà comment cela se fait. Étant donné que l'étiquette contient déjà les informations sur la police, leur inclusion dans cet appel de méthode est triviale.
CGSize size = [label.text sizeWithFont:label.font
constrainedToSize:CGSizeMake(maxWidth, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
CGRect labelFrame = label.frame;
labelFrame.size.height = size.height;
label.frame = labelFrame;
Version Swift utilisant le boundingRectWithSize
le plus à jour:
let maxHeight = CGFloat.infinity
let rect = label.attributedText?.boundingRectWithSize(CGSizeMake(maxWidth, maxHeight),
options: .UsesLineFragmentOrigin, context: nil)
var frame = label.frame
frame.size.height = rect.size.height
label.frame = frame
Vous pouvez obtenir le même résultat avec sizeThatFits.
CGSize size = [label sizeThatFits:CGSizeMake(label.frame.size.width, CGFLOAT_MAX)];
CGRect frame = label.frame;
frame.size.height = size.height;
label.frame = frame;
Ou alternativement, avec sizeToFit.
CGRect frame = label.frame;
[label sizeToFit];
frame.size.height = label.frame.size.height;
label.frame = frame;
sizeToFit fonctionne très bien. Le seul problème est qu'il est basé sur la taille actuelle du contrôle.
Par exemple, si vous recyclez des cellules de vue tabulaire avec une étiquette, l'étiquette peut avoir été réduite en largeur dans une cellule précédente et donc, l'appel à sizeToFit peut sembler peu fiable.
Réinitialisez simplement la largeur d'origine de votre contrôle avant d'envoyer le message sizeToFit.
c = CGSize (largeur: votreLargeur, hauteur: CGFloat.greatestFiniteMagnitude)
result = sizeThatFits (c) .height
Donc...
let t = .... your UITextView
let w = .... your known width of the item
let trueHeight = t.sizeThatFits(
CGSize(width: t, height: CGFloat.greatestFiniteMagnitude)).height
C'est ça.
Très souvent, vous voulez connaître la différence en hauteur par rapport à une entrée "normale" sur une ligne .
Cela se produit en particulier si vous créez une sorte de cellules qui n'ont rien à voir avec UTableView (par exemple, une sorte de vue de pile personnalisée). Vous devez définir la hauteur manuellement à un moment donné. Sur votre storyboard, construisez-le comme vous le souhaitez, en utilisant un exemple de texte de n'importe quelle chaîne courte (par exemple, "A") qui bien sûr n'aura qu'une seule ligne dans une situation normale. Ensuite, vous faites quelque chose comme ça ...
func setTextWithSizeCorrection() { // an affaire iOS
let t = .... your UITextView
let w = .... your known width of the item
let oneLineExample = "A"
let actualText = yourDataSource[row].description.whatever
// get the height as if with only one line...
experimental.text = oneLineExample
let oneLineHeight = t.sizeThatFits(
CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)).height
// get the height with the actual long text...
// (note that usually, you do not want a one-line minimum)
experimental.text = (actualText == "") ? oneLineExample : actualText
let neededHeight = t.sizeThatFits(
CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)).height
experimental.text = actualText
let delta = neededHeight - oneLineHeight
set the height of your cell, or whatever it is(standardHeight + delta)
}
Dernier point: l'une des choses vraiment stupides dans iOS est que UITextView a une sorte de marge bizarre à l'intérieur. Cela signifie que vous ne pouvez pas simplement basculer entre UITextViews et les étiquettes; et cela cause de nombreux autres problèmes. Apple n'a pas résolu ce problème au moment de l'écriture. Pour résoudre le problème est difficile: l'approche suivante est généralement OK:
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero;
textContainer.lineFragmentPadding = 0;
}
}
UITextView cassé et inutilisable d'Apple ...
UITextViewFixed
qui est, dans la plupart des cas, un correctif acceptable:
(Jaune ajouté pour plus de clarté.)
Je pense que vous ne devriez pas utiliser le NSString
size...
méthodes, UILabel
possède déjà une API pour cela, comme le souligne @vatrif (qui utilise probablement en interne uniquement les méthodes de NSString
).
Néanmoins, je pense que l'API de UILabel
pourrait être améliorée. C'est pourquoi je pense qu'une catégorie serait la solution la plus élégante:
// UILabel+Resize.h
@interface UILabel (Resize)
- (void)sizeToFitHeight;
@end
// UILabel+Resize.m
@implementation UILabel (Resize)
- (void)sizeToFitHeight {
CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)];
CGRect frame = self.frame;
frame.size.height = size.height;
self.frame = frame;
}
@end
Juste une chose: je ne suis pas sûr du nom approprié pour cette méthode:
Commentaires très appréciés, merci!
Une API agréée bénéficierait de cet ajout. Simplifiez-vous la vie et ajoutez une extension à la classe UILabel dans Swift comme suit:
extension UILabel {
func sizeToFitHeight() {
let size:CGSize = self.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max))
var frame:CGRect = self.frame
frame.size.height = size.height
self.frame = frame
}
}
Une extension facile pour ce problème pour Swift 3.
extension UILabel {
func sizeToFitHeight() {
let size: CGSize = self.sizeThatFits(CGSize.init(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
var frame:CGRect = self.frame
frame.size.height = size.height
self.frame = frame
}
}
SOLUTION FIXE POUR Swift
Utilisez CGFloat.greatestFiniteMagnitude
Pour maxHeight.
let size = CGSize.init(width: yourLabel.frame.size.width,
height: CGFloat.greatestFiniteMagnitude)
let rect = errorLabel.attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
var frame = errorLabel.frame
frame.size.height = (rect?.size.height)!
errorLabel.frame = frame
OU Créez l'extension UIlabel
et appelez la méthode yourLabel. sizeToFitHeight()
extension UILabel {
func sizeToFitHeight() {
let maxHeight : CGFloat = CGFloat.greatestFiniteMagnitude
let size = CGSize.init(width: self.frame.size.width, height: maxHeight)
let rect = self.attributedText?.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
var frame = self.frame
frame.size.height = (rect?.size.height)!
self.frame = frame
}
}
Version Swift 3 de Mundi réponse:
let maxHeight: CGFloat = 10000
let rect = label.attributedText!.boundingRect(with: CGSize(width: maxWidth, height: maxHeight),
options: .usesLineFragmentOrigin,
context: nil)
var frame = labe.frame
frame.size.height = rect.size.height
label.frame = frame