【问题标题】:Dynamically sizing text with kerning to occupy the full width of a UILabel使用字距动态调整文本大小以占据 UILabel 的整个宽度
【发布时间】:2014-08-18 10:18:45
【问题描述】:

我有一个带有UILabel 的布局,位于固定宽度视图上方,如下所示为灰色矩形。

文字需要与固定灰色视图的宽度相匹配。

我通过将UILabel 上的adjustsFontSizeToFitWidth 属性设置为YES,将字体大小设置为非常大,并将minimumScaleFactor 设置为适当的小来实现这一点。 这一直很好,直到……

我不得不为所述文本添加字距调整。我通过将@{NSKernAttributeName: @1.40} 应用于属性字符串来添加字距调整,然后传递属性字符串UILabelattributedText 属性。不幸的是,这似乎阻碍了自动缩放,因为这会导致文本被正确紧缩,但字符串的结尾被截断。好像标签在不考虑字距调整的情况下缩小了文本。

如何让给定的字符串 with kerning 以我选择的宽度(即灰色视图的宽度)呈现?

【问题讨论】:

  • 你读过这个问题吗? stackoverflow.com/questions/7370013/…
  • @iBug 我说问题不是重复的。他实际上是在以编程方式调整标签大小以适合文本。我希望调整属性文本以适合标签。这很可能实际上是对 Apple 的疏忽,在这种情况下我将提交 Radar。

标签: cocoa-touch uilabel


【解决方案1】:

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

此扩展使用 quicksort 的思想来快速找到使字符串适合所需宽度的字距调整。

请注意,紧缩小于-3.0会使难看的字符重叠,所以如果字符串不适合紧缩=-3,算法只会返回-3。当然你可以将 bigKern 变量设置为更小的值。

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

希望你喜欢。

@implementation NSString(扩展)

- (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:

// 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];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    相关资源
    最近更新 更多