it-swarm.com.de

Dynamische Änderung der Schriftgröße von UILabel

Ich habe derzeit ein UILabel:

factLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 280, 100)];
factLabel.text = @"some text some text some text some text";
factLabel.backgroundColor = [UIColor clearColor];
factLabel.lineBreakMode = UILineBreakModeWordWrap;
factLabel.numberOfLines = 10;
[self.view addSubview:factLabel];

Während der gesamten Lebensdauer meiner iOS-Anwendung erhält factLabel eine Reihe verschiedener Werte. Einige mit mehreren Sätzen, andere mit nur 5 oder 6 Wörtern.

Wie kann ich UILabel so einstellen, dass sich die Schriftgröße ändert, sodass der Text immer in die von mir definierten Grenzen passt?

179
CodeGuy

Einzeilig:

factLabel.numberOfLines = 1;
factLabel.minimumFontSize = 8;
factLabel.adjustsFontSizeToFitWidth = YES;

Der obige Code passt die Schriftgröße Ihres Texts auf (zum Beispiel) 8 versucht, Ihren Text in das Etikett einzufügen. numberOfLines = 1 ist obligatorisch.

Mehrere Zeilen:

Zum numberOfLines > 1 Es gibt eine Methode, um die Größe des endgültigen Texts mit NSStrings sizeWithFont: ... UIKit-Zusatzmethoden zu ermitteln, zum Beispiel:

CGSize lLabelSize = [yourText sizeWithFont:factLabel.font
                                  forWidth:factLabel.frame.size.width
                             lineBreakMode:factLabel.lineBreakMode];

Danach können Sie die Größe Ihres Etiketts beispielsweise mit dem Ergebnis lLabelSize ändern (vorausgesetzt, Sie ändern nur die Höhe des Etiketts):

factLabel.frame = CGRectMake(factLabel.frame.Origin.x, factLabel.frame.Origin.y, factLabel.frame.size.width, lLabelSize.height);

iOS6

Einzeilig:

Ab iOS6 ist minimumFontSize veraltet. Die Linie

factLabel.minimumFontSize = 8.;

kann geändert werden in:

factLabel.minimumScaleFactor = 8./factLabel.font.pointSize;

iOS7

Mehrere Zeilen:

Ab iOS7 ist sizeWithFont veraltet. Mehrzeiliger Fall reduziert sich auf:

factLabel.numberOfLines = 0;
factLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize maximumLabelSize = CGSizeMake(factLabel.frame.size.width, CGFLOAT_MAX);
CGSize expectSize = [factLabel sizeThatFits:maximumLabelSize];
factLabel.frame = CGRectMake(factLabel.frame.Origin.x, factLabel.frame.Origin.y, expectSize.width, expectSize.height);
343
Martin Babacaev

minimumFontSize ist mit iOS 6 veraltet. Sie können minimumScaleFactor verwenden.

yourLabel.adjustsFontSizeToFitWidth=YES;
yourLabel.minimumScaleFactor=0.5;

Dabei wird Ihre Schriftgröße entsprechend der Breite des Etiketts und des Texts berücksichtigt.

67
Amit Singh

Basierend auf der Antwort von @Eyal Ben Dov möchten Sie möglicherweise eine Kategorie erstellen, damit Sie diese flexibel in anderen Apps von Ihnen verwenden können.

Anmerkung: Ich habe seinen Code aktualisiert, um ihn mit iOS 7 kompatibel zu machen

- Header-Datei

#import <UIKit/UIKit.h>

@interface UILabel (DynamicFontSize)

-(void) adjustFontSizeToFillItsContents;

@end

- Implementierungsdatei

#import "UILabel+DynamicFontSize.h"

@implementation UILabel (DynamicFontSize)

#define CATEGORY_DYNAMIC_FONT_SIZE_MAXIMUM_VALUE 35
#define CATEGORY_DYNAMIC_FONT_SIZE_MINIMUM_VALUE 3

-(void) adjustFontSizeToFillItsContents
{
    NSString* text = self.text;

    for (int i = CATEGORY_DYNAMIC_FONT_SIZE_MAXIMUM_VALUE; i>CATEGORY_DYNAMIC_FONT_SIZE_MINIMUM_VALUE; i--) {

        UIFont *font = [UIFont fontWithName:self.font.fontName size:(CGFloat)i];
        NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName: font}];

        CGRect rectSize = [attributedText boundingRectWithSize:CGSizeMake(self.frame.size.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil];

        if (rectSize.size.height <= self.frame.size.height) {
            self.font = [UIFont fontWithName:self.font.fontName size:(CGFloat)i];
            break;
        }
    }

}

@end

- Usage

#import "UILabel+DynamicFontSize.h"

[myUILabel adjustFontSizeToFillItsContents];

Prost

24

Einzelne Zeile - Es gibt zwei Möglichkeiten, die Sie einfach ändern können.

1- Pragmatisch (Swift 3)

Fügen Sie einfach den folgenden Code hinzu

    yourLabel.numberOfLines = 1;
    yourLabel.minimumScaleFactor = 0.7;
    yourLabel.adjustsFontSizeToFitWidth = true;

2 - Verwenden des UILabel Attributes-Inspektors

i- Select your label- Set number of lines 1.
ii- Autoshrink-  Select Minimum Font Scale from drop down
iii- Set Minimum Font Scale value as you wish , I have set 0.7 as in below image. (default is 0.5)

enter image description here

22
Devendra Singh

Es ist 2015. Ich musste nach einem Blog-Post suchen, in dem erklärt wird, wie es für die neueste Version von iOS und XCode mit Swift funktioniert, damit es mit mehreren Zeilen funktioniert.

  1. stellen Sie "Autoshrink" auf "Minimale Schriftgröße".
  2. stelle die Schrift auf die größte wünschenswerte Schriftgröße ein (ich habe 20 gewählt)
  3. Ändern Sie "Zeilenumbrüche" von "Zeilenumbruch" in "Ende abschneiden".

Quelle: http://beckyhansmeyer.com/2015/04/09/autoshrinking-text-in-a-multiline-uilabel/

20
zavtra

Schnelle Version:

textLabel.adjustsFontSizeToFitWidth = true
textLabel.minimumScaleFactor = 0.5
12
Esqarrouth

Hier ist eine Swift Erweiterung für UILabel. Sie führt einen binären Suchalgorithmus aus, um die Schriftgröße basierend auf der Breite und Höhe der Etikettengrenzen zu ändern. Getestet für iOS 9 und Autolayout.

SAGE: Wobei <label> Ihr vordefiniertes UILabel ist, dessen Schriftgröße geändert werden muss

<label>.fitFontForSize()

Standardmäßig sucht diese Funktion im Bereich der Schriftgrößen 5pt und 300pt und stellt die Schriftart so ein, dass sie dem Text "perfekt" innerhalb der Grenzen entspricht (genau innerhalb von 1,0pt). Sie können die Parameter so definieren, dass beispielsweise zwischen 1pt und aktuelle Schriftgröße des Etiketts genau innerhalb .1pts gesucht wird :

<label>.fitFontForSize(1.0, maxFontSize: <label>.font.pointSize, accuracy:0.1)

Kopieren Sie den folgenden Code/fügen Sie ihn in Ihre Datei ein

extension UILabel {

    func fitFontForSize(var minFontSize : CGFloat = 5.0, var maxFontSize : CGFloat = 300.0, accuracy : CGFloat = 1.0) {
        assert(maxFontSize > minFontSize)
        layoutIfNeeded() // Can be removed at your own discretion
        let constrainedSize = bounds.size
        while maxFontSize - minFontSize > accuracy {
            let midFontSize : CGFloat = ((minFontSize + maxFontSize) / 2)
            font = font.fontWithSize(midFontSize)
            sizeToFit()
            let checkSize : CGSize = bounds.size
            if  checkSize.height < constrainedSize.height && checkSize.width < constrainedSize.width {
                minFontSize = midFontSize
            } else {
                maxFontSize = midFontSize
            }
        }
        font = font.fontWithSize(minFontSize)
        sizeToFit()
        layoutIfNeeded() // Can be removed at your own discretion
    }

}

HINWEIS: Jeder der layoutIfNeeded() Aufrufe kann nach eigenem Ermessen entfernt werden

7
Avi Frankl

Es ist ein bisschen nicht raffiniert, aber das sollte funktionieren. Nehmen wir zum Beispiel an, Sie möchten Ihr uilabel auf 120x120 mit einer maximalen Schriftgröße von 28 begrenzen:

magicLabel.numberOfLines = 0;
magicLabel.lineBreakMode = NSLineBreakByWordWrapping;
...
magicLabel.text = text;
    for (int i = 28; i>3; i--) {
        CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:(CGFloat)i] constrainedToSize:CGSizeMake(120.0f, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
        if (size.height < 120) {
            magicLabel.font = [UIFont systemFontOfSize:(CGFloat)i];
            break;
        }
    }
4
Eyal Ben Dov

Senden Sie einfach die sizeToFit-Nachricht an UITextView. Es passt seine eigene Höhe an den Text an. Es ändert weder seine eigene Breite noch seinen Ursprung.

[textViewA1 sizeToFit];
1
codercat

Hier ist der Füllcode einer UILabel-Unterklasse, die eine Änderung der animierten Schriftgröße implementiert:

@interface SNTextLayer : CATextLayer

@end

@implementation SNTextLayer

- (void)drawInContext:(CGContextRef)ctx {
    // We override this to make text appear at the same vertical positon as in UILabel
    // (otherwise it's shifted tdown)
    CGFloat height = self.bounds.size.height;
    float fontSize = self.fontSize;
    // May need to adjust this somewhat if it's not aligned perfectly in your implementation
    float yDiff = (height-fontSize)/2 - fontSize/10;

    CGContextSaveGState(ctx);
    CGContextTranslateCTM(ctx, 0.0, yDiff);
    [super drawInContext:ctx];
     CGContextRestoreGState(ctx);
}

@end

@interface SNAnimatableLabel ()

@property CATextLayer* textLayer;

@end

@interface SNAnimatableLabel : UILabel

- (void)animateFontToSize:(CGFloat)fontSize withDuration:(double)duration;

@end



@implementation SNAnimatableLabel


- (void)awakeFromNib {
    [super awakeFromNib];
    _textLayer = [SNTextLayer new];
    _textLayer.backgroundColor = self.backgroundColor.CGColor;
    _textLayer.foregroundColor = self.textColor.CGColor;
    _textLayer.font = CGFontCreateWithFontName((CFStringRef)self.font.fontName);
    _textLayer.frame = self.bounds;
    _textLayer.string = self.text;
    _textLayer.fontSize = self.font.pointSize;
    _textLayer.contentsScale = [UIScreen mainScreen].scale;
    [_textLayer setPosition: CGPointMake(CGRectGetMidX(_textLayer.frame), CGRectGetMidY(_textLayer.frame))];
    [_textLayer setAnchorPoint: CGPointMake(0.5, 0.5)];
    [_textLayer setAlignmentMode: kCAAlignmentCenter];
    self.textColor = self.backgroundColor;
    // Blend text with background, so that it doens't interfere with textlayer text
    [self.layer addSublayer:_textLayer];
    self.layer.masksToBounds = NO;
}

- (void)setText:(NSString *)text {
    _textLayer.string = text;
    super.text = text;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    // Need to enlarge the frame, otherwise the text may get clipped for bigger font sizes
    _textLayer.frame = CGRectInset(self.bounds, -5, -5);
}

- (void)animateFontToSize:(CGFloat)fontSize withDuration:(double)duration {
    [CATransaction begin];
    [CATransaction setAnimationDuration:duration];
    _textLayer.fontSize = fontSize;
    [CATransaction commit];
}
0
videolist

Diese Lösung funktioniert für mehrzeilige:

Nachdem ich mehreren Artikeln gefolgt war und eine Funktion benötigt hatte, die den Text automatisch skaliert und die Zeilenanzahl so anpasst, dass sie am besten zur angegebenen Etikettengröße passt, habe ich selbst eine Funktion geschrieben. (dh eine kurze Zeichenfolge würde gut in eine Zeile passen und eine große Menge des Etikettenrahmens verwenden, während eine lange Zeichenfolge automatisch in zwei oder drei Zeilen aufgeteilt und die Größe entsprechend angepasst würde.)

Sie können es jederzeit wiederverwenden und nach Bedarf optimieren. Stellen Sie sicher, dass Sie es aufrufen, nachdem viewDidLayoutSubviews beendet wurde, damit der anfängliche Beschriftungsrahmen festgelegt wurde.

+ (void)setFontForLabel:(UILabel *)label withMaximumFontSize:(float)maxFontSize andMaximumLines:(int)maxLines {
    int numLines = 1;
    float fontSize = maxFontSize;
    CGSize textSize; // The size of the text
    CGSize frameSize; // The size of the frame of the label
    CGSize unrestrictedFrameSize; // The size the text would be if it were not restricted by the label height
    CGRect originalLabelFrame = label.frame;

    frameSize = label.frame.size;
    textSize = [label.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize: fontSize]}];

    // Work out the number of lines that will need to fit the text in snug
    while (((textSize.width / numLines) / (textSize.height * numLines) > frameSize.width / frameSize.height) && (numLines < maxLines)) {
        numLines++;
    }

    label.numberOfLines = numLines;

    // Get the current text size
    label.font = [UIFont systemFontOfSize:fontSize];
    textSize = [label.text boundingRectWithSize:CGSizeMake(frameSize.width, CGFLOAT_MAX)
                                        options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                     attributes:@{NSFontAttributeName : label.font}
                                        context:nil].size;

    // Adjust the frame size so that it can fit text on more lines
    // so that we do not end up with truncated text
    label.frame = CGRectMake(label.frame.Origin.x, label.frame.Origin.y, label.frame.size.width, label.frame.size.width);

    // Get the size of the text as it would fit into the extended label size
    unrestrictedFrameSize = [label textRectForBounds:CGRectMake(0, 0, label.bounds.size.width, CGFLOAT_MAX) limitedToNumberOfLines:numLines].size;

    // Keep reducing the font size until it fits
    while (textSize.width > unrestrictedFrameSize.width || textSize.height > frameSize.height) {
        fontSize--;
        label.font = [UIFont systemFontOfSize:fontSize];
        textSize = [label.text boundingRectWithSize:CGSizeMake(frameSize.width, CGFLOAT_MAX)
                                            options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                         attributes:@{NSFontAttributeName : label.font}
                                            context:nil].size;
        unrestrictedFrameSize = [label textRectForBounds:CGRectMake(0, 0, label.bounds.size.width, CGFLOAT_MAX) limitedToNumberOfLines:numLines].size;
    }

    // Set the label frame size back to original
    label.frame = originalLabelFrame;
}
0
aaroncatlin

Swift 2.0 Version:

private func adapteSizeLabel(label: UILabel, sizeMax: CGFloat) {
     label.numberOfLines = 0
     label.lineBreakMode = NSLineBreakMode.ByWordWrapping
     let maximumLabelSize = CGSizeMake(label.frame.size.width, sizeMax);
     let expectSize = label.sizeThatFits(maximumLabelSize)
     label.frame = CGRectMake(label.frame.Origin.x, label.frame.Origin.y, expectSize.width, expectSize.height)
}
0
Phil