web-dev-qa-db-fra.com

UILabel ne réduit pas automatiquement le texte à la taille de l'étiquette

J'ai cet étrange problème et je le traite depuis plus de 8 heures maintenant. En fonction de la situation, je dois calculer la taille UILabels de manière dynamique,
par exemple 
ma UIViewController reçoit un événement et je change de UILabels taille. du plus grand au plus petit. La taille de ma UILabel devient plus petite et la taille requise est correcte, mais le texte dans ma UILabel reste identique, la même taille de police, etc. J'ai besoin que la police soit plus petite pour que tout le texte s'adapte à la UILabel. La question est donc de savoir comment adapter le texte à mon étiquette avec autoshrinking ou quelque chose du genre.

Dans ma xib, UILabelsautoshrink est cochée, aussi le nombre de lignes est défini sur 0, et ma chaîne comporte de nouveaux symboles de ligne (\ n) et j'ai sélectionné linebreakmode to wordwrap. Peut-être que quelqu'un était dans la même situation que moi et pourrait m'aider? Ça me plairait vraiment.

Merci d'avance!

EDIT: UILabel la taille de police minimale est fixée à 10

98
Lukas

Si vous cherchez toujours une meilleure solution, je pense que c'est ce que vous voulez:

Une valeur booléenne indiquant si la taille de la police doit être réduite afin d’adapter la chaîne de titre au rectangle de délimitation de l’étiquette. (Cette propriété est effective uniquement lorsque la propriété numberOfLines est définie sur 1.)

@property(nonatomic) BOOL adjustsFontSizeToFitWidth

Une valeur booléenne indiquant si l'espacement entre les lettres doit être ajusté pour correspondre à la chaîne située dans le rectangle de délimitation de l'étiquette.

@property(nonatomic) BOOL adjustsLetterSpacingToFitWidth

La source .

146
lester

C’est ainsi que j’obtiens le travail UILabel Autoshrink (en particulier pour la hauteur d’adaptation des polices d’étiquette dans le périphérique 4s de 6s Plus Storyboard) sous iOS 9.2, Xcode 7.2 ...

 enter image description here

  • Nombre de lignes est 0
  • Sauts de ligne: Clip
  • Autoshrink: échelle de police minimale 0.25
105
ohho

minimumFontSize est obsolète dans iOS 6.

Utilisez donc minimumScaleFactor au lieu de minmimumFontSize.

lbl.adjustsFontSizeToFitWidth=YES;
lbl.minimumScaleFactor=0.5;
60
user2681543

ma solution est aussi l'étiquette booléenne.adjustsFontSizeToFitWidth = YES; BUT. Vous devez, dans l’interface Builder, basculer l’option Word Wrapping sur "CLIP" . Ensuite, réduisez automatiquement les étiquettes. C'est très important.

18
loki-e

Vous pouvez écrire comme

UILabel *reviews = [[UILabel alloc]initWithFrame:CGRectMake(14, 13,270,30)];//Set frame
reviews.numberOfLines=0;
reviews.textAlignment = UITextAlignmentLeft;
reviews.font = [UIFont fontWithName:@"Arial Rounded MT Bold" size:12];
reviews.textColor=[UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.8]; 
reviews.backgroundColor=[UIColor clearColor];

Vous pouvez calculer le nombre de lignes comme ça

CGSize maxlblSize = CGSizeMake(270,9999);
CGSize totalSize = [reviews.text sizeWithFont:reviews.font 
              constrainedToSize:maxlblSize lineBreakMode:reviews.lineBreakMode];

CGRect newFrame =reviews.frame;
newFrame.size.height = totalSize.height;
reviews.frame = newFrame;

CGFloat reviewlblheight = totalSize.height;

int lines=reviewlblheight/12;//12 is the font size of label

UILabel *lbl=[[UILabel alloc]init];
lbl.frame=CGRectMake(140,220 , 100, 25);//set frame as your requirement
lbl.font=[UIFont fontWithName:@"Arial" size:20];
[lbl setAutoresizingMask:UIViewContentModeScaleAspectFill];
[lbl setLineBreakMode:UILineBreakModeClip];
lbl.adjustsFontSizeToFitWidth=YES;//This is main for shrinking font
lbl.text=@"HelloHelloHello";

J'espère que cela vous aidera: -) En attendant votre réponse 

5
Birju

Ceci est pour Swift 3 sous Xcode 8.2.1 (8C1002) 

La meilleure solution que j'ai trouvée consiste à définir une largeur fixe dans votre Storyboard ou dans votre IB sur l'étiquette. Définissez vos contraintes avec contraindre aux marges. Dans votre viewDidLoad, ajoutez les lignes de code suivantes:

override func viewDidLoad() {
            super.viewDidLoad()

            label.numberOfLines = 1
            label.adjustsFontSizeToFitWidth = true
            label.minimumScaleFactor = 0.5
        }

 label constraints to margin

 fixed width label constraints to margin

 attributes inspector

Cela a fonctionné comme un charme et ne déborde pas sur une nouvelle ligne et réduit le texte à la largeur de l'étiquette sans problèmes étranges et fonctionne dans Swift 3.

4
Robert Mcelvenny

Dans Swift 3 (par programme), je devais le faire:

let lbl = UILabel()
lbl.numberOfLines = 0
lbl.lineBreakMode = .byClipping
lbl.adjustsFontSizeToFitWidth = true
lbl.minimumScaleFactor = 0.5
lbl.font = UIFont.systemFont(ofSize: 15)
4
Naloiko Eugene

En fin de compte, je n'ai pas trouvé ma réponse. Et je pense que l'autoshrink ne fonctionne pas pour plusieurs lignes. J'ai fini par utiliser suggestion dans ce lien: autoshrink sur un UILabel avec plusieurs lignes

La solution consiste à calculer la hauteur du texte à une largeur donnée et, si le texte est plus grand, à réduire la taille de la police, puis à refaire la même chose jusqu'à ce que la hauteur soit égale ou inférieure à la taille souhaitée.

Je ne comprends pas pourquoi cela devrait être si difficile à mettre en œuvre. Si quelque chose me manque, tout le monde est invité à me corriger :)

3
Lukas

Je pense que vous pouvez écrire le code ci-dessous après alloc init Label  

UILabel* lbl = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, 280, 50)];
lbl.text = @"vbdsbfdshfisdhfidshufidhsufhdsf dhdsfhdksbf hfsdh fksdfidsf sdfhsd fhdsf sdhfh sdifsdkf ksdhfkds fhdsf dsfkdsfkjdhsfkjdhskfjhsdk fdhsf ";
[lbl setMinimumFontSize:8.0];
[lbl setNumberOfLines:0];
[lbl setFont:[UIFont systemFontOfSize:10.0]];
lbl.lineBreakMode = UILineBreakModeWordWrap;
lbl.backgroundColor = [UIColor redColor];
[lbl sizeToFit];
[self.view addSubview:lbl];

Ça marche bien avec moi. Utilise-le

2
iDhaval

Deux ans plus tard, et cette question est toujours d'actualité ...

Dans iOS 8/XCode 6.1, je constatais parfois que ma UILabel (créée dans une UITableViewCell, avec AutoLayout activé et des contraintes souples lui permettant de disposer de beaucoup d'espace) ne se redimensionnait pas pour s'adapter à la chaîne de texte.

La solution, comme les années précédentes, consistait à définir le texte et puis call sizeToFit.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    . . .
    cell.lblCreatedAt.text = [note getCreatedDateAsString];
    [cell.lblCreatedAt sizeToFit];
}

(Soupir.)

2
Mike Gledhill

Sous iOS 9, je devais simplement:

  1. Ajoutez des contraintes à gauche et à droite de l'étiquette à la vue d'ensemble.
  2. Définissez le mode de saut de ligne sur le découpage dans IB.
  3. Définissez le nombre de lignes sur 1 dans IB.

Quelqu'un a recommandé de définir le nombre de lignes sur 0, mais pour moi, cela a simplement obligé l'étiquette à afficher plusieurs lignes.

2
Nick Yap

C'est une excellente question, car il semblerait que cela ferait déjà partie de la fonctionnalité intégrée UIKit ou d'un cadre associé. Voici un bon exemple visuel de la question:

Font resizing animation

Il n'y a pas de solution facile, mais c'est tout à fait possible. Pour cela, vous pouvez essayer différentes tailles de police par programmation jusqu'à ce que vous en trouviez une qui s'adapte raisonnablement aux limites de la vue. Vous pouvez accomplir cela avec la fonction boundingRect() de NSString ou NSAttributedString. Par exemple:

let string = "This is a test"
let infiniteSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height:CGFloat.greatestFiniteMagnitude)
let size = string.boundingRect(with: infiniteSize, options: [], attributes: [.font: UIFont.systemFont(ofSize: avgSize)] context: nil).size

Vous pouvez faire une recherche binaire pour être plus efficace qu'une approche complète de la force brute. Certaines considérations sont également un peu plus complexes, notamment le bon habillage de Word et les performances de la mise en cache des polices iOS, si vous recherchez quelque chose de vraiment robuste.

Si vous souhaitez uniquement afficher facilement le texte à l'écran, j'ai développé une implémentation robuste dans Swift, que j'utilise également dans une application de production. C'est une sous-classe UIView avec une mise à l'échelle automatique efficace des polices pour tout texte saisi, y compris les lignes multiples. Pour l'utiliser, vous feriez simplement quelque chose comme:

let view = AKTextView()
// Use a simple or fancy NSAttributedString
view.attributedText = .init(string: "Some text here")
// Add to the view hierarchy somewhere

C'est tout! Vous pouvez trouver la source complète ici: https://github.com/FlickType/AccessibilityKit

J'espère que cela t'aides!

1
Kosta Eleftheriou

ne fonctionne pas si numberOfLines > 1 Ce que j'ai fait une condition comme celle-ci-

if(lblRecLocation.text.length > 100)
    lblRecLocation.font = [UIFont fontWithName:@"app_font_name" size:10];
1
Vaibhav Saran

Voici comment le faire. Supposons le message suivantLabel est l’étiquette que vous voulez avoir pour l’effet souhaité. Maintenant, essayez ces simples lignes de codes:

    //SET THE WIDTH CONSTRAINTS FOR LABEL.
    CGFloat constrainedWidth = 240.0f;//YOU CAN PUT YOUR DESIRED ONE,THE MAXIMUM WIDTH OF YOUR LABEL.
 //CALCULATE THE SPACE FOR THE TEXT SPECIFIED.
    CGSize sizeOfText=[yourText sizeWithFont:yourFont constrainedToSize:CGSizeMake(constrainedWidth, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
    UILabel *messageLabel=[[UILabel alloc] initWithFrame:CGRectMake(20,20,constrainedWidth,sizeOfText.height)];
    messageLabel.text=yourText;
    messageLabel.numberOfLines=0;//JUST TO SUPPORT MULTILINING.
1
Anand

Arriver en retard à la fête, mais comme j'avais l'exigence supplémentaire d'avoir un mot par ligne, cette addition m'a fait l'affaire:

label.numberOfLines = [labelString componentsSeparatedByString:@" "].count;

Docs Apple dire:

Normalement, le texte de l'étiquette est dessiné avec la police que vous spécifiez dans la propriété de police. Toutefois, si cette propriété est définie sur OUI et que le texte de la propriété dépasse le rectangle de délimitation de l'étiquette, le destinataire commence à réduire la taille de la police jusqu'à ce que la chaîne soit ajustée ou que la taille de police minimale soit atteinte. Sous iOS 6 et versions antérieures, cette propriété est effective uniquement lorsque la propriété numberOfLines est définie sur 1.

Mais c'est un mensonge. Un mensonge je vous le dis! C'est vrai pour toutes les versions d'iOS. En particulier, cela est vrai lorsque vous utilisez une UILabel dans une UICollectionViewCell dont la taille est déterminée par des contraintes ajustées dynamiquement à l'exécution via une présentation personnalisée (ex. self.menuCollectionViewLayout.itemSize = size).

Ainsi, lorsqu'il est utilisé conjointement avec adjustsFontSizeToFitWidth et minimumScaleFactor, comme indiqué dans les réponses précédentes, la définition par programme de numberOfLines en fonction du nombre de mots a résolu le problème de la réduction automatique de la taille. Faire quelque chose de similaire en fonction du nombre de mots ou même du nombre de caractères peut produire une solution "suffisamment proche".

0
Justin Whitney

Dans Swift 4 (par programme): 

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200.0, height: 200.0))
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 0

label.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."

view.addSubview(label)
0

Swift 4, Xcode 9.4.1

La solution qui a fonctionné pour moi: J'avais un label dans une cellule de vue de collection , et le texte de l'étiquette était en train d'être coupé . Définissez les attributs comme ci-dessous sur Storyboard

Lines = 0
LineBreak = Word Wrap
Set yourlabel's leading and trailing constraint = 0 (using Autolayout)
0
Naishta