AutoLayout 链接两个 UILabels 以具有相同的字体大小 [英] AutoLayout link two UILabels to have the same font size

查看:20
本文介绍了AutoLayout 链接两个 UILabels 以具有相同的字体大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个 UILabel 并排成一排,左右调整使其看起来如下所示.

I have two UILabels next to each other in row with left and right adjustments so that it looks like below.

 |-Some text left adjusted----------some other text right adjusted-|

两个标签都有 adjustsFontSizeToFitWidth = YES 并通过以下约束相互链接

Both labels have adjustsFontSizeToFitWidth = YES and are linked to each other with the following constraint

[NSLayoutConstraint constraintWithItem:_rightLabel
                    attribute:NSLayoutAttributeLeft
                    relatedBy:NSLayoutRelationGreaterThanOrEqual
                    toItem:_leftLabel
                    attribute:NSLayoutAttributeRight
                    multiplier:1
                    constant:10]

这样它们就可以尽可能多地占用空间,如果原始字体大小没有足够的空间,那么由于 adjustsFontSizeToFitWidth 会降低原始字体大小,这样就不会截断文本.

So that they take up as much space as they can and if there is not enough space for the original font size it will be lowered thanks to adjustsFontSizeToFitWidth so that no text is truncated.

我的问题是,当一个由于长文本而需要降低其字体大小时,我希望另一个标签也降低其字体大小,以便两者的大小相同,而不是一个大小可能是另一个的两倍.我也想限制字体大小以匹配,但是我不知道该怎么做,有什么想法吗?

My problem is that when one needs to lower its font size due to long text i want the other label to lower its font size as well so that both are the same size instead of one being perhaps twice the size of the other. I would like to constraint the font size as well to match but alas i do not know how to this, any ideas?

推荐答案

来自 关于 adjustsFontSizeToWidth 的 UILabel 文档:

From the UILabel documentation on adjustsFontSizeToWidth:

通常,标签文本使用您在 font 属性中指定的字体绘制.但是,如果此属性设置为 YES,并且 text 属性中的文本超出了标签的边界矩形,则接收器开始减小字体大小,直到字符串适合或达到最小字体大小.

Normally, the label text is drawn with the font you specify in the font property. If this property is set to YES, however, and the text in the text property exceeds the label’s bounding rectangle, the receiver starts reducing the font size until the string fits or the minimum font size is reached.

我由此推断更新的字体是在绘制时计算的,并且font 属性只读取,不写入.因此,我相信 Andrew 在 font 属性上使用 KVO 的建议是行不通的.

I infer from this that the updated font is calculated at drawing time, and the font property is only read, not written to. Therefore, I believe the suggestion by Andrew to use KVO on the font property will not work.

因此,要获得您想要的结果,您需要计算调整后的字体大小.

Consequently, to achieve the result you want, you'll need to calculate the adjusted font size.

正如 Jackson 在评论中指出的那样,这种非常方便的 NSString 方法 用于获取实际字体已在 iOS 7 中被弃用. 从技术上讲,您仍然可以使用它,直到它被删除.

As Jackson notes in the comments, this very convenient NSString method to get the actual font has been deprecated in iOS 7. Technically, you could still use it until it's removed.

另一种选择是遍历字体比例,直到找到适合两个标签的字体比例.我能够让它正常工作;这是一个示例项目,展示了我是如何做到的.

Another alternative is to loop through font scales until you find one that will fit both labels. I was able to get it working fine; here's a sample project that shows how I did it.

此外,这是防止链接停止工作的代码:

Also, here's the code in case that link ever stops working:

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:_rightLabel
                                                                  attribute:NSLayoutAttributeLeft
                                                                  relatedBy:NSLayoutRelationGreaterThanOrEqual
                                                                     toItem:_leftLabel
                                                                  attribute:NSLayoutAttributeRight
                                                                 multiplier:1
                                                                   constant:10];

    [self.view addConstraint:constraint];
}

- (IBAction)makeRightLabelLongerPressed:(id)sender {
    self.rightLabel.text = @"some much longer right label text";
}

- (IBAction)adjustLabelSizes:(id)sender {
    NSLog(@"Attempting to adjust label sizes…");

    CGFloat minimumScaleFactor = fmaxf(self.rightLabel.minimumScaleFactor, self.leftLabel.minimumScaleFactor);;
    UIFont * startingFont = self.rightLabel.font;

    for (double currentScaleFactor = 1.0; currentScaleFactor > minimumScaleFactor; currentScaleFactor -= 0.05) {
        UIFont *font = [startingFont fontWithSize:startingFont.pointSize * currentScaleFactor];
        NSLog(@"  Attempting font with scale %f (size = %f)…", currentScaleFactor, font.pointSize);

        BOOL leftLabelWorks = [self wouldThisFont:font workForThisLabel:self.leftLabel];
        BOOL rightLabelWorks = [self wouldThisFont:font workForThisLabel:self.rightLabel];
        if (leftLabelWorks && rightLabelWorks) {
            NSLog(@"    It fits!");
            self.leftLabel.font = font;
            self.rightLabel.font = font;
            return;
        } else {
            NSLog(@"    It didn't fit. :-(");
        }

    }

    NSLog(@"  It won't fit without violating the minimum scale (%f), so set both to minimum.  Some text may get truncated.", minimumScaleFactor);

    UIFont *minimumFont = [self.rightLabel.font fontWithSize:self.rightLabel.font.pointSize * self.rightLabel.minimumScaleFactor];
    self.rightLabel.font = minimumFont;
    self.leftLabel.font = minimumFont;
}

- (BOOL) wouldThisFont:(UIFont *)testFont workForThisLabel:(UILabel *)testLabel {
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:testFont, NSFontAttributeName, nil];
    NSAttributedString *as = [[NSAttributedString alloc] initWithString:testLabel.text attributes:attributes];
    CGRect bounds = [as boundingRectWithSize:CGSizeMake(CGRectGetWidth(testLabel.frame), CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin) context:nil];
    BOOL itWorks = [self doesThisSize:bounds.size fitInThisSize:testLabel.bounds.size];
    return itWorks;
}

- (BOOL)doesThisSize:(CGSize)aa fitInThisSize:(CGSize)bb {
    if ( aa.width > bb.width ) return NO;
    if ( aa.height > bb.height ) return NO;
    return YES;
}

这种方法可以简单地重构为一个类别方法,以取代 Jackson 链接的已弃用方法.

This approach could be trivially refactored into a category method that replaces the deprecated method linked to by Jackson.

这篇关于AutoLayout 链接两个 UILabels 以具有相同的字体大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆