一个UILabel中不同大小的顶部对齐文本(Top-aligning text of differe

2019-08-17 19:17发布

如何顶部对齐一个UILabel中不同大小的文字? 一个例子是在价格横幅较大尺寸的金额顶部对准较小尺寸的百分之量。

在的UILabel支持iOS6的NSAttributedString ,让我有相同的UILabel不同大小的文字。 然而,它似乎并没有对顶部对齐文本的属性。 什么是实现这个选项? 在我看来,这提供了一个自定义绘制逻辑做基于自定义属性串钥匙上对齐可能是最好的,但我不知道如何去做。

Answer 1:

我可以用一个标签来实现你想要的结果。

使用一点数学可以抵消较小的文本,以达到您想要的结果的基线。

Objective-C的

- (NSMutableAttributedString *)styleSalePriceLabel:(NSString *)salePrice withFont:(UIFont *)font
{
    if ([salePrice rangeOfString:@"."].location == NSNotFound) {
        return [[NSMutableAttributedString alloc] initWithString:salePrice];
    } else {
        NSRange range = [salePrice rangeOfString:@"."];
        range.length = (salePrice.length - range.location);
        NSMutableAttributedString *stylizedPriceLabel = [[NSMutableAttributedString alloc] initWithString:salePrice];
        UIFont *smallFont = [UIFont fontWithName:font.fontName size:(font.pointSize / 2)];
        NSNumber *offsetAmount = @(font.capHeight - smallFont.capHeight);
        [stylizedPriceLabel addAttribute:NSFontAttributeName value:smallFont range:range];
        [stylizedPriceLabel addAttribute:NSBaselineOffsetAttributeName value:offsetAmount range:range];
        return stylizedPriceLabel;
    }
}

迅速

extension Range where Bound == String.Index {
    func asNSRange() -> NSRange {
        let location = self.lowerBound.encodedOffset
        let length = self.lowerBound.encodedOffset - self.upperBound.encodedOffset
        return NSRange(location: location, length: length)
    }
}

extension String {
    func asStylizedPrice(using font: UIFont) -> NSMutableAttributedString {
        let stylizedPrice = NSMutableAttributedString(string: self, attributes: [.font: font])

        guard var changeRange = self.range(of: ".")?.asNSRange() else {
            return stylizedPrice
        }

        changeRange.length = self.count - changeRange.location
        // forgive the force unwrapping
        let changeFont = UIFont(name: font.fontName, size: (font.pointSize / 2))!
        let offset = font.capHeight - changeFont.capHeight
        stylizedPrice.addAttribute(.font, value: changeFont, range: changeRange)
        stylizedPrice.addAttribute(.baselineOffset, value: offset, range: changeRange)
        return stylizedPrice
    }
}

我们得到以下:



Answer 2:

与试图仅仅通过对齐框架的起源要做到这一点的问题是“正常”的人物通常与周围有些微胖结束了,因为标签必须满足所有字体的字符,包括那些将高大的伸长伸。 您将您发布,如果更小的“99”均是被设置为相同的来源更大的文本单独的标签,那将是因为美元符号的最顶部点过高的图像中发现。

幸运的是, UIFont为我们提供了我们需要做这个正确的所有信息。 我们需要测量该标签使用的是空伸的空间和调整的相对位置来考虑它,就像这样:

//Make sure the labels hug their contents
[self.bigTextLabel sizeToFit];
[self.smallTextLabel sizeToFit];

//Figure out the "blank" space above normal character height for the big text
UIFont *bigFont = self.bigTextLabel.font;
CGFloat bigAscenderSpace = (bigFont.ascender - bigFont.capHeight);

//Move the small text down by that ammount
CGFloat smallTextOrigin = CGRectGetMinY(self.bigTextLabel.frame) + bigAscenderSpace;

//Figure out the "blank" space above normal character height for the little text
UIFont *smallFont = self.smallTextLabel.font;
CGFloat smallAscenderSpace = smallFont.ascender - smallFont.capHeight;

//Move the small text back up by that ammount
smallTextOrigin -= smallAscenderSpace;

//Actually assign the frames
CGRect smallTextFrame = self.smallTextLabel.frame;
smallTextFrame.origin.y = smallTextOrigin;
self.smallTextLabel.frame = smallTextFrame;

(此代码假定你有两个名为标注属性bigTextLabelsmallTextLabel ,分别)


编辑:

没有两个标签这样做是相当类似的。 您可以自定义UIView子类和借鉴NSAttributedStrings在它与-drawInRect:options:context:方法(请务必使用NSStringDrawingUsesLineFragmentOrigin在你的选择)。 为制定顶部对齐数学应该是一样的,唯一的区别是你通过得到从属性串的字体NSFontAttributeName属性,而不是标签。 在属性串图纸的WWDC 2012的视频是一个很好的参考。



文章来源: Top-aligning text of different sizes within a UILabel