使用多行自动收缩UILabel

jfi*_*isk 56 uilabel ios ios5

是否可以在一个UILabel?上的多行上结合使用autoshrink属性?例如,2个可用行上可能的大文本大小.

DaG*_*aMs 46

我稍微修改了上面的代码,使其成为一个类别UILabel:

头文件:

#import <UIKit/UIKit.h>
@interface UILabel (MultiLineAutoSize)
    - (void)adjustFontSizeToFit;
@end
Run Code Online (Sandbox Code Playgroud)

和实施文件:

@implementation UILabel (MultiLineAutoSize)

- (void)adjustFontSizeToFit
{
    UIFont *font = self.font;
    CGSize size = self.frame.size;

    for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumFontSize; maxSize -= 1.f)
    {
        font = [font fontWithSize:maxSize];
        CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
        CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
        if(labelSize.height <= size.height)
        {
            self.font = font;
            [self setNeedsLayout];
            break;
        }
    }
    // set the font to the minimum size anyway
    self.font = font;
    [self setNeedsLayout];
}

@end
Run Code Online (Sandbox Code Playgroud)

  • 这是完美的,但在iOS6中不推荐使用minimumFontSize - 如何将其更改为使用minimumScaleFactor? (5认同)

小智 40

我找到了这个链接http://beckyhansmeyer.com/2015/04/09/autoshrinking-text-in-a-multiline-uilabel/

使用Interface Builder可以通过3个简单步骤解决问题:

  1. 将"自动收缩"设置为"最小字体大小".
  2. 将字体设置为您想要的最大字体大小(20),并将Lines设置为10,在我的情况下,该行数与该字体大小的标签中的行数相同.
  3. 然后,将"换行符"从"自动换行"更改为"截断尾巴".

希望能帮助到你!

  • 比自定义代码更好的解决方案。好工作。 (2认同)
  • 感谢您指出“截尾”,这就是一切的不同之处。 (2认同)

The*_*ude 39

这些人找到了解决方案:

http://www.11pixel.com/blog/28/resize-multi-line-text-to-fit-uilabel-on-iphone/

他们的解决方案如下:

int maxDesiredFontSize = 28;
int minFontSize = 10;
CGFloat labelWidth = 260.0f;
CGFloat labelRequiredHeight = 180.0f;
//Create a string with the text we want to display.
self.ourText = @"This is your variable-length string. Assign it any way you want!";

/* This is where we define the ideal font that the Label wants to use.
   Use the font you want to use and the largest font size you want to use. */
UIFont *font = [UIFont fontWithName:@"Marker Felt" size:maxDesiredFontSize];

int i;
/* Time to calculate the needed font size.
   This for loop starts at the largest font size, and decreases by two point sizes (i=i-2)
   Until it either hits a size that will fit or hits the minimum size we want to allow (i > 10) */
for(i = maxDesiredFontSize; i > minFontSize; i=i-2)
{
    // Set the new font size.
    font = [font fontWithSize:i];
    // You can log the size you're trying: NSLog(@"Trying size: %u", i);

    /* This step is important: We make a constraint box 
       using only the fixed WIDTH of the UILabel. The height will
       be checked later. */ 
    CGSize constraintSize = CGSizeMake(labelWidth, MAXFLOAT);

    // This step checks how tall the label would be with the desired font.
    CGSize labelSize = [self.ourText sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

    /* Here is where you use the height requirement!
       Set the value in the if statement to the height of your UILabel
       If the label fits into your required height, it will break the loop
       and use that font size. */
    if(labelSize.height <= labelRequiredHeight)
        break;
}
// You can see what size the function is using by outputting: NSLog(@"Best size is: %u", i);

// Set the UILabel's font to the newly adjusted font.
msg.font = font;

// Put the text into the UILabel outlet variable.
msg.text = self.ourText;
Run Code Online (Sandbox Code Playgroud)

为了使其工作,必须在接口构建器中为UILabel分配IBOutlet.

"IBOutlet UILabel*msg;"

所有的优点都是11pixel的人.


ste*_*ulr 24

这是基于针对iOS 6的itecedor更新而更新到iOS 7的类别解决方案.

头文件:

#import <UIKit/UIKit.h>
@interface UILabel (MultiLineAutoSize)
    - (void)adjustFontSizeToFit;
@end
Run Code Online (Sandbox Code Playgroud)

和实施文件:

@implementation UILabel (MultiLineAutoSize)


- (void)adjustFontSizeToFit {
    UIFont *font = self.font;
    CGSize size = self.frame.size;

    for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor * self.font.pointSize; maxSize -= 1.f)
    {
        font = [font fontWithSize:maxSize];
        CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);

        CGRect textRect = [self.text boundingRectWithSize:constraintSize
                                             options:NSStringDrawingUsesLineFragmentOrigin
                                          attributes:@{NSFontAttributeName:font}
                                             context:nil];

        CGSize labelSize = textRect.size;


        if(labelSize.height <= size.height)
        {
            self.font = font;
            [self setNeedsLayout];
            break;
        }
    }
    // set the font to the minimum size anyway
    self.font = font;
    [self setNeedsLayout]; }


@end
Run Code Online (Sandbox Code Playgroud)

  • 您是否需要将minimumScaleFactor应用于初始pointSize?(例如,如果因子是0.5,你可以在这里获得非常小的字体). (2认同)

Gol*_*Joe 14

标记为解决方案的答案是hacky和不精确.如果正确设置以下属性,UILabel将自动处理它:

numberOfLines 必须非零

adjustsFontSizeToFitWidth 一定是 YES

lineBreakMode一定不能NSLineBreakByCharWrappingNSLineBreakByWordWrapping

  • 令人惊讶的是,即使在今天,这个答案仍然如此真实。如果可以的话我本可以给它100个赞!这似乎非常违反直觉,不能设置 .byWordWrapping 才能使其正常工作 - 花了几个小时试图弄清楚它。 (3认同)
  • 我成功地使用了:numberOfLines = 0, lineBreakMode = NSLineBreakByTruncatingTail(或 NSLineBreakByTruncatingHead 或 NSLineBreakByTruncatingMiddle)并在标签上设置了高度限制。 (2认同)

wfb*_*ale 8

一个改编自@DaGaMs的版本.

SWIFT 2:

extension UILabel {
    func adjustFontSizeToFit(minimumFontSize: CGFloat, maximumFontSize: CGFloat? = nil) {
        let maxFontSize = maximumFontSize ?? font.pointSize
        for size in stride(from: maxFontSize, to: minimumFontSize, by: -CGFloat(0.1)) {
            let proposedFont = font.fontWithSize(size)
            let constraintSize = CGSizeMake(bounds.size.width, CGFloat(MAXFLOAT))
            let labelSize = ((text ?? "") as NSString).boundingRectWithSize(constraintSize,
                options: .UsesLineFragmentOrigin,
                attributes: [NSFontAttributeName: proposedFont],
                context: nil)
            if labelSize.height <= bounds.size.height {
                font = proposedFont
                setNeedsLayout()
                break;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

SWIFT 3:

extension UILabel {
    func adjustFontSizeToFit(minimumFontSize: CGFloat, maximumFontSize: CGFloat? = nil) {
        let maxFontSize = maximumFontSize ?? font.pointSize
        for size in stride(from: maxFontSize, to: minimumFontSize, by: -CGFloat(0.1)) {
            let proposedFont = font.withSize(size)
            let constraintSize = CGSize(width: bounds.size.width, height: CGFloat(MAXFLOAT))
            let labelSize = ((text ?? "") as NSString).boundingRect(with: constraintSize,
                                                                            options: .usesLineFragmentOrigin,
                                                                            attributes: [NSFontAttributeName: proposedFont],
                                                                            context: nil)
            if labelSize.height <= bounds.size.height {
                font = proposedFont
                setNeedsLayout()
                break;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Nem*_*Nem 7

由于声誉不足,我无法评论MontiRabbit的帖子,所以我会做出新的答案.他(和她的推荐人)提出的解决方案不适用于Xcode 7.3或更好,它是不精确的.为了使它工作,在故事板中,我不得不:

  1. 设置宽度约束(纯宽度或尾部和引线)
  2. 设置一个HEIGHT CONSTRAINT(这非常重要,通常使用自动调整大小不设置标签高度)
  3. 将"自动收缩"属性设置为"最小字体比例"或"最小字体大小"(适用于两种情况)
  4. 将"Line Breaks"属性设置为"Truncate Tail"
  5. 将"Lines"属性设置为非零值

希望能帮助到你!;)


joh*_*doe 6

我喜欢DaGaMs的答案,但是在使用可以返回dequeueReusableCell:的UITableViewCells中的标签时,常规字体大小会继续缩小,即使原始字体大小仍然需要一些文本较少的tableView单元并且可以利用原始标签的原始字体大小.

所以,我从DaGaMs的类别开始作为跳跃点,我创建了一个单独的类而不是一个单独的类,我确保我的故事板中的UILabel使用这个新类:

#import "MultiLineAutoShrinkLabel.h"

@interface MultiLineAutoShrinkLabel ()
@property (readonly, nonatomic) UIFont* originalFont;
@end

@implementation MultiLineAutoShrinkLabel

@synthesize originalFont = _originalFont;

- (UIFont*)originalFont { return _originalFont ? _originalFont : (_originalFont = self.font); }

- (void)quoteAutoshrinkUnquote
{
    UIFont* font = self.originalFont;
    CGSize frameSize = self.frame.size;

    CGFloat testFontSize = _originalFont.pointSize;
    for (; testFontSize >= self.minimumFontSize; testFontSize -= 0.5)
    {
        CGSize constraintSize = CGSizeMake(frameSize.width, MAXFLOAT);
        CGSize testFrameSize = [self.text sizeWithFont:(font = [font fontWithSize:testFontSize])
                                     constrainedToSize:constraintSize
                                         lineBreakMode:self.lineBreakMode];
        // the ratio of testFontSize to original font-size sort of accounts for number of lines
        if (testFrameSize.height <= frameSize.height * (testFontSize/_originalFont.pointSize))
            break;
    }

    self.font = font;
    [self setNeedsLayout];
}

@end
Run Code Online (Sandbox Code Playgroud)


Abr*_*ras 6

itedcedor的答案有一个问题,普维特曼指出.此外,不需要修剪空格.这是修改后的版本:

- (void)adjustFontSizeToFit {
    UIFont *font = self.font;
    CGSize size = self.frame.size;

    for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor * self.font.pointSize; maxSize -= 1.f) {
        font = [font fontWithSize:maxSize];
        CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
        CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];

        if(labelSize.height <= size.height) {
            self.font = font;
            [self setNeedsLayout];
            break;
        }
    }

    // set the font to the minimum size anyway
    self.font = font;
    [self setNeedsLayout];
}
Run Code Online (Sandbox Code Playgroud)