使用字距调整功能动态调整文本大小以占据UILabel的整个宽度 [英] Dynamically sizing text with kerning to occupy the full width of a UILabel

查看:95
本文介绍了使用字距调整功能动态调整文本大小以占据UILabel的整个宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的布局中有 UILabel 放在固定宽度视图上方,下面显示为灰色矩形。

I have a layout with a UILabel placed above a fixed width view, shown below as a grey rectangle.

文本我需要通过匹配固定的灰色视图的宽度。

The text needs to match the width of the fixed grey view.

我是通过将 adjustsFontSizeToFitWidth 属性设置为 UILabel 设置为,将字体大小设置为非常大的值,并设置 minimumScaleFactor 到合适的小东西。 这一直很好,直到...

I achieved this by setting the adjustsFontSizeToFitWidth property on the UILabel to YES, settings the font size to something really large, and setting the minimumScaleFactor to something suitable small. This worked fine until…

我不得不在上述文本中添加字距调整。我通过将 @ {NSKernAttributeName:@ 1.40} 应用于属性字符串来添加字距调整,然后通过属性字符串 UILabel attributedText 属性。不幸的是,这似乎阻碍了自动缩放,因为这会导致文本正确调整字距,但是字符串的末尾被截断。好像标签缩小文本时没有考虑字距调整。

I had to add kerning to said text. I added the kerning by applying @{NSKernAttributeName: @1.40} to an attributed string and then passed the attributed string UILabel’s attributedText property. Unfortunately this seems to stump the automatic scaling, as this results in the text being properly kerned but the end of the string is truncated. It is as though the label scaled the text down without taking kerning into account.

如何获取带有字距调整的给定字符串 我选择的宽度(即灰色视图的宽度)?

How can I get a given string with kerning to be rendered with a width of my choosing (i.e. the grey view's width)?

推荐答案

我正在使用下一个代码来计算字距调整(通过创建NSString扩展名)。

I am using next code to calculate kerning (by creating NSString extension).

此扩展名使用 quicksort 透视的思想快速找到使字串适合所需字距的字距调整

This extension is using quicksort idea of pivot to quickly find kerning that makes the string fit into the needed width.

请注意,字距小于-3.0 会使丑陋的字符重叠,因此,如果字符串不适合kerning = -3,则字符串算法只会返回-3。当然,您可以将 bigKern 变量设置为较小的值。

Please note that kerning less than -3.0 makes ugly characters overlap, so if string is not fitting with kerning = -3, the algorithm just returns -3. Of course you can set bigKern variable to smaller value.

我对照 UITabBarItem 进行了检查(Apple使用标签栏项目标签上的字距调整),与我的实现非常相似。

I checked it against UITabBarItem's (Apple uses kerning on tab bar item labels), and my implementation is very similar.

希望您喜欢它。

@implementation NSString(扩展名)

@implementation NSString (Extension)

- (CGFloat)kernForFont:(UIFont *)font toFitWidth:(CGFloat)width
{
    CGSize size = CGSizeMake(CGFLOAT_MAX, font.pointSize*2); // Size to fit.

    const CGFloat threshold = 0.1;
    CGFloat bigKern = -3.0, smallKern = 0.0, pivot = 0.0;
    NSMutableDictionary *attrs = [NSMutableDictionary new];
    attrs[NSFontAttributeName] = font;

    while (true) {
        attrs[NSKernAttributeName] = @(pivot);

        CGRect frame = [self boundingRectWithSize:size
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:attrs
                                          context:nil];
        CGFloat diff = width - frame.size.width;
        if (diff > -0.5) {
            // String is fitting.
            if (pivot == 0.0) // Fits without kerning.
                return pivot;
            else if (smallKern - bigKern <= threshold)
                return pivot; // Threshold is reached, return the fitting pivot.
            else {
                // Pivot is fitting, but threshold is not reached, set pivot as max.
                bigKern = pivot;
            }
        }
        else {
            // String not fitting.
            smallKern = pivot;
            if (smallKern - bigKern <= threshold)
                return bigKern;
        }
        pivot = (smallKern + bigKern) / 2.0;
    }

    return bigKern;
}

@end

示例用法,用于自定义UITabBarItems:

Example usage, for custom UITabBarItems:

// I have a tabBarItem of type UITabBarItem. textColor is a UIColor.
NSString *title = tabBarItem.title;

CGFloat textLabelWidth = tabBar.frame.size.width / (CGFloat)(self.tabBar.items.count) - 6.0; // 6 is padding.

UIFont *font = [UIFont systemFontOfSize:10.0];
CGFloat kern = [title kernForFont:font toFitWidth:textLabelWidth];

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.alignment = NSTextAlignmentCenter;

NSDictionary *attrs = @{
                        NSFontAttributeName: font,
                        NSKernAttributeName: @(kern),
                        NSForegroundColorAttributeName: textColor,
                        NSParagraphStyleAttributeName: paragraphStyle
                        };
textLabel.attributedText = [[NSAttributedString alloc] initWithString:title attributes:attrs];

这篇关于使用字距调整功能动态调整文本大小以占据UILabel的整个宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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