Top-aligning text of different sizes within a UILabel

前端 未结 2 1141
渐次进展
渐次进展 2021-02-01 18:10

How to top-align text of different sizes within a UILabel? An example is top-aligning smaller-sized cent amount with larger-sized dollar amount in price banners.

2条回答
  •  再見小時候
    2021-02-01 18:22

    I was able to achieve your desired result using a single label.

    Using a little math you can offset the baseline of the smaller text to achieve your desired result.

    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;
        }
    }
    

    Swift

    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
        }
    }
    

    This yields the following:

提交回复
热议问题