AutoLayout链接两个UILabel以具有相同的字体大小

Alz*_*orz 23 uilabel ios autolayout

我有两个UILabel排在一起,左右调整,所以它看起来像下面.

 |-Some text left adjusted----------some other text right adjusted-|
Run Code Online (Sandbox Code Playgroud)

两个标签都有adjustsFontSizeToFitWidth = YES,并使用以下约束相互链接

[NSLayoutConstraint constraintWithItem:_rightLabel
                    attribute:NSLayoutAttributeLeft
                    relatedBy:NSLayoutRelationGreaterThanOrEqual
                    toItem:_leftLabel
                    attribute:NSLayoutAttributeRight
                    multiplier:1
                    constant:10]
Run Code Online (Sandbox Code Playgroud)

因此,它们占用尽可能多的空间,如果没有足够的空间用于原始字体大小,则会因为adjustsFontSizeToFitWidth而降低,因此不会截断任何文本.

我的问题是,当由于长文本需要降低其字体大小时,我希望另一个标签也降低其字体大小,以便两者都是相同的大小而不是一个大小可能是另一个大小的两倍.我想约束字体大小以匹配但唉我不知道如何这样,任何想法?

Aar*_*ger 14

UILabel文档adjustsFontSizeToWidth:

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

我从中推断,更新的字体是在绘图时计算的,并且font只读取属性,而不是写入.因此,我相信安德鲁建议在font物业上使用KVO是行不通的.

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

正如杰克逊在评论中指出的那样,在iOS 7中已经弃用了这种非常方便的获取实际字体的NSString方法.从技术上讲,你可以在删除它之前使用它.

另一种方法是循环使用字体比例,直到找到适合两种标签的字体.我能够让它正常工作; 这是一个示例项目,展示了我是如何做到的.

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

- (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;
}
Run Code Online (Sandbox Code Playgroud)

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


And*_*rew -1

您可以尝试使用键值观察来观察一个标签上字体属性的更改,当发生变化时,将另一个标签设置为使用相同的字体。

在你的-viewDidLoad方法中:

// Add self as an observer of _rightLabel's font property
[_rightLabel addObserver:self forKeyPath:@"font" options:NSKeyValueObservingOptionNew context:NULL];
Run Code Online (Sandbox Code Playgroud)

在同一控制器实现中(上述代码片段上下文中的 self):

// Observe changes to the font property of _rightLabel
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (object == _rightLabel && [keyPath isEqualToString:@"font"]) {
        // Set _leftLabel's font property to be the new value set on _rightLabel
        _leftLabel.font = change[NSKeyValueChangeNewKey];
    }
}
Run Code Online (Sandbox Code Playgroud)