24

UILabel内で異なるサイズのテキストを上揃えにする方法は? 例としては、価格バナーで小さいサイズのセント額を大きいサイズのドル額の上に揃えることです。

サンプル画像

NSAttributedStringiOS6 の UILabelは、同じ UILabel に異なるサイズのテキストを含めることをサポートしています。ただし、テキストを上揃えにする属性はないようです。これを実装するためのオプションは何ですか? カスタム属性の文字列キーに基づいて上揃えを行うためのカスタム描画ロジックを提供するのが最善のように思えますが、どうすればよいかわかりません。

4

4 に答える 4

56

単一のラベルを使用して、ご希望の結果を得ることができました。

ちょっとした計算を使用して、小さいテキストのベースラインをオフセットして、目的の結果を得ることができます。

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

これにより、次の結果が得られます。

于 2014-08-26T23:23:11.220 に答える
10

フレームの起点を揃えるだけでこれを行おうとすると問題になるのは、「通常の」文字の周囲に余分なパディングが発生することです。これは、ラベルが、背の高いアセンダーと長いディセンダーを含むすべてのフォントの文字に対応する必要があるためです。投稿した画像で、小さい「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;

bigTextLabel(このコードは、それぞれとという名前の 2 つのラベル プロパティがあることを前提としていますsmallTextLabel)


編集:

2 つのラベルなしでこれを行うことはかなり似ています。カスタム UIView サブクラスを作成NSAttributedStringsし、-drawInRect:options:context:メソッドで描画できます (必ずNSStringDrawingUsesLineFragmentOriginオプションで使用してください)。上部の配置を計算するための計算は同じである必要があります。唯一の違いNSFontAttributeNameは、ラベルではなく、属性を介して属性付き文字列からフォントを取得することです。これについては、2012 年の WWDC の属性付き弦の描画に関するビデオが参考になります。

于 2013-03-21T04:22:52.483 に答える
0

考えられるアプローチの 1 つは、ラベルを、入力するテキストの正確なサイズにすることです。

CGRect labelFrame;
//Set the origin of the label to whatever you want
labelFrame.size = [label.text sizeWithFont:label.font];  //If using NSString
labelFrame.size = [label.text size];                     //If using NSAttributedString
label.frame = labelFrame;

詳細については、この同様の SO 投稿を参照してください

于 2013-03-21T00:54:46.013 に答える