Je dessine UILabels
par programme. Ils obtiennent leurs tailles d'une base de données. Je ne peux donc pas simplement utiliser sizeToFit
. J'ai déjà implémenté une fonction qui redessine UILabels
avec un ratio passé. Donc, tout ce que j'ai besoin de trouver, c’est le texte dans UILabel
de mon point de vue qui exigerait le ratio maximum pour redessiner UILabels
. Donc, finalement, je dois faire quelque chose comme ceci:
double ratio = 1.00;
for (UILabel* labels in sec.subviews) {
float widthLabel = labels.frame.size.width;
float heightLabel = labels.frame.size.height;
float heightText = //get the text height here
float widthText = //get the text width here
if (widthLabel < widthText) {
ratio = MAX(widthText/widthLabel,ratio);
}
if (heightLabel < heightText) {
ratio = MAX(heightText/heightLabel, ratio);
}
}
//redraw UILabels with the given ratio here
Alors, comment puis-je obtenir la hauteur et la largeur d'un texte, certains de mes textes ne rentrant pas dans l'étiquette, je ne peux pas simplement utiliser les limites de l'étiquette? J'utilise Xcode 5 et iOS 7.
Le problème avec
CGRect r = [text boundingRectWithSize:CGSizeMake(200, 0)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}
context:nil];
est boundingRectWithSize
qui détermine la valeur maximale que CGRect peut avoir.
Ma solution à ce problème est de vérifier si elle dépasse, sinon le texte peut tenir dans l'étiquette. Je l'ai fait en utilisant des boucles.
NSString *text = @"This is a long sentence. Wonder how much space is needed?";
CGFloat width = 100;
CGFloat height = 100;
bool sizeFound = false;
while (!sizeFound) {
NSLog(@"Begin loop");
CGFloat fontSize = 14;
CGFloat previousSize = 0.0;
CGFloat currSize = 0.0;
for (float fSize = fontSize; fSize < fontSize+6; fSize++) {
CGRect r = [text boundingRectWithSize:CGSizeMake(width, height)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fSize]}
context:nil];
currSize =r.size.width*r.size.height;
if (previousSize >= currSize) {
width = width*11/10;
height = height*11/10;
fSize = fontSize+10;
}
else {
previousSize = currSize;
}
NSLog(@"fontSize = %f\tbounds = (%f x %f) = %f",
fSize,
r.size.width,
r.size.height,r.size.width*r.size.height);
}
if (previousSize == currSize) {
sizeFound = true;
}
}
NSLog(@"Size found with width %f and height %f", width, height);
Après chaque itération, la taille et la largeur augmentent de 10% de sa valeur.
La raison pour laquelle j'ai choisi 6, c'est parce que je ne voulais pas que l'étiquette soit trop épaisse.
Pour une solution n'utilisant pas de boucles:
NSString *text = @"This is a long sentence. Wonder how much space is needed?";
CGFloat width = 100;
CGFloat height = 100;
CGFloat currentFontSize = 12;
CGRect r1 = [text boundingRectWithSize:CGSizeMake(width, height)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize+6]}
context:nil];
CGRect r2 = [text boundingRectWithSize:CGSizeMake(width, height)
options:NSStringDrawingUsesFontLeading
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:currentFontSize+6]}
context:nil];
CGFloat firstVal =r1.size.width*r1.size.height;
CGFloat secondVal =r2.size.width*r2.size.height;
NSLog(@"First val %f and second val is %f", firstVal, secondVal);
if (secondVal > firstVal) {
float initRat = secondVal/firstVal;
float ratioToBeMult = sqrtf(initRat);
width *= ratioToBeMult;
height *= ratioToBeMult;
}
NSLog(@"Final width %f and height %f", width, height);
//for verifying
for (NSNumber *n in @[@(12.0f), @(14.0f), @(17.0f)]) {
CGFloat fontSize = [n floatValue];
CGRect r = [text boundingRectWithSize:CGSizeMake(width, height)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}
context:nil];
NSLog(@"fontSize = %f\tbounds = (%f x %f) = %f",
fontSize,
r.size.width,
r.size.height,r.size.width*r.size.height);
firstVal =r.size.width*r.size.height;
}
Où la dernière boucle est la preuve qu'une police plus grande peut donner un résultat de taille supérieure.
Toutes les méthodes [NSString sizeWithFont...]
sont obsolètes dans iOS 7. Utilisez plutôt cette option.
CGRect labelRect = [text
boundingRectWithSize:labelSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{
NSFontAttributeName : [UIFont systemFontOfSize:14]
}
context:nil];
Voir aussi https://developer.Apple.com/documentation/foundation/nsstring/1619914-sizewithfont .
Par votre commentaire, j'ai fait un test simple. Le code et la sortie sont ci-dessous.
// code to generate a bounding rect for text at various font sizes
NSString *text = @"This is a long sentence. Wonder how much space is needed?";
for (NSNumber *n in @[@(12.0f), @(14.0f), @(18.0f)]) {
CGFloat fontSize = [n floatValue];
CGRect r = [text boundingRectWithSize:CGSizeMake(200, 0)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}
context:nil];
NSLog(@"fontSize = %f\tbounds = (%f x %f)",
fontSize,
r.size.width,
r.size.height);
}
cela produit la sortie suivante (notez que les limites changent comme prévu à mesure que la taille de la police augmente):
fontSize = 12.000000 bounds = (181.152008 x 28.632000)
fontSize = 14.000000 bounds = (182.251999 x 50.105999)
fontSize = 18.000000 bounds = (194.039993 x 64.421997)
Longueur obtient le nombre de caractères. Si vous voulez obtenir la largeur du texte:
Objectif c
CGSize textSize = [label.text sizeWithAttributes:@{NSFontAttributeName:[label font]}];
Swift 4
let size = label.text?.size(withAttributes: [.font: label.font]) ?? .zero
Cela vous donne la taille. Et vous pouvez comparer le textSize.width
de chaque étiquette.
Un autre moyen simple de faire cela que je n'ai pas encore vu mentionné:
CGSize textSize = [label intrinsicContentSize];
(Cela ne fonctionne correctement qu'après que vous ayez défini le texte et la police de l'étiquette, bien sûr.)
Voici une variante de Swift.
let font = UIFont(name: "HelveticaNeue", size: 25)!
let text = "This is some really long text just to test how it works for calculating heights in Swift of string sizes. What if I add a couple lines of text?"
let textString = text as NSString
let textAttributes = [NSFontAttributeName: font]
textString.boundingRectWithSize(CGSizeMake(320, 2000), options: .UsesLineFragmentOrigin, attributes: textAttributes, context: nil)
Petit conseil les gars, si comme moi vous utilisez, boundingRectWithSize
with [UIFont systemFontOFSize:14]
Si votre chaîne est longue de deux lignes, la hauteur du rectangle retournée est quelque chose comme 33,4 points.
Ne commettez pas l'erreur, comme moi, de la transformer en un int
, car 33,4 devient 33 et l'étiquette de hauteur 33 points passe de deux à une ligne!
En utilisant cette ligne de code, nous pouvons obtenir la taille du texte sur l'étiquette.
let str = "Sample text"
let size = str.sizeWithAttributes([NSFontAttributeName:UIFont.systemFontOfSize(17.0)])
Donc, nous pouvons utiliser à la fois la largeur et la hauteur.
Une solution qui fonctionne avec des étiquettes multilignes (Swift 4), pour calculer la hauteur à partir d’une largeur fixe:
let label = UILabel(frame: .zero)
label.numberOfLines = 0 // multiline
label.font = UIFont.systemFont(ofSize: UIFont.labelFontSize) // your font
label.preferredMaxLayoutWidth = width // max width
label.text = "This is a sample text.\nWith a second line!" // the text to display in the label
let height = label.intrinsicContentSize.height
msgStr string obtenir la taille:
let msgStr:NSString = Data["msg"]! as NSString
let messageSize = msgStr.boundingRect(with: CGSize(width: ChatTable.frame.width-116, height: CGFloat.infinity), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName:UIFont(name: "Montserrat-Light", size: 14)!], context: nil).size
Swift 3.0
func getLabelHeight() -> CGFloat {
let font = UIFont(name: "OpenSans", size: 15)!
let textString = "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." as NSString
let textAttributes = [NSFontAttributeName: font]
let rect = textString.boundingRect(with: CGSize(width: 320, height: 2000), options: .usesLineFragmentOrigin, attributes: textAttributes, context: nil)
return rect.size.height
}