UILabel斜体字体剪辑

时间:2015-11-29 17:25:35

标签: ios objective-c uilabel uifont

我试图解决这个问题,因为在我正在处理的应用程序中我有很多字体,所以当用户更改字体时,标签的大小会被动态计算。

我遇到的问题是,如果字体是斜体,那么UILabel会被剪裁在最后:如下图所示:

UILabel clipping example

这是我到目前为止所尝试的:

  • 借助CoreText和CGSize CTFramesetterSuggestFrameSizeWithConstraints ( CTFramesetterRef framesetter, CFRange stringRange, CFDictionaryRef frameAttributes, CGSize constraints, CFRange *fitRange );
  • 计算宽度
  • 借助NSAttributedString和- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context
  • 计算宽度
  • 借助NSString和- (CGSize)sizeWithAttributes:(NSDictionary<NSString *,id> *)attrs
  • 计算宽度
  • 使用temp UITextView和sizeThatFits´ and fitToSize`

由于应用程序中有很多字体,我需要动态设置标签的宽度,因此UILabel的子类化以及在drawFrameInRect上添加更多的点是行不通的。

以下是Github上的示例代码。

感谢任何帮助/建议。

8 个答案:

答案 0 :(得分:1)

CGSize size = [label.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0f]}];
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));

并从adjustSize更新标签的宽度和高度。希望它能正常工作

答案 1 :(得分:1)

这对我有用。

func labelThatFits(_ title: String) -> UILabel {
    let titleLabel = UILabel()
    titleLabel.font = UIFont(name: fontName, size: 20)
    titleLabel.text = title
    titleLabel.textAlignment = .center
    titleLabel.widthAnchor.constraint(equalToConstant: titleLabel.intrinsicContentSize.width + 10).isActive = true
    return titleLabel
}

答案 2 :(得分:0)

我会在您的按钮和标签上使用自动布局,始终根据您选择标签的字体大小使其居中。

然后,删除updateLabel方法中的所有代码。我不确定你为什么使用UITextview并将爵士乐带入画面。如果您在故事板中单击标签并检查属性检查器并找到&#34; Autoshrink&#34;它应设置为&#34;最小字体大小&#34; NOT&#34;固定字体大小。&#34;

然后我会在您的标签上使用NSAttributedString根据点击的按钮更改其大小和字体。

答案 3 :(得分:0)

我下载了你的GitHub项目,看来UILabel和UITextField肯定是以不同的方式计算文本的边界。所以,我首先尝试将UITextField上sizeToFit的结果大小分配给UILabel的大小。但是,这种方法打破了Strato字体。

在尝试了其他一些失败的方法之后,我记得斜体字体或多或少都是相同的角度。字体的斜体版本通常会将边界框的宽度增加与原始宽度相同的比例。

<强>更新

因此,您应该能够从宽度和字体大小派生斜体字符串的宽度。我在您的项目中尝试过这种方法,它适用于您列出的所有字体。我使用了以下公式:

  

CGRect calculatedRect = [attributedString boundingRectWithSize:CGSizeMake(CGFLOAT_MAX,CGFLOAT_MAX)选项:(NSStringDrawingUsesLineFragmentOrigin)context:nil];

     

calculatedRect.size.width = calculatedRect.size.width +(label.font.pointSize * 0.2);

由于这取决于斜体加入的宽度,因此斜体粗体字体(如Strata)会对宽度产生更大的影响。

显然,如果文本API被扩充以包含文本宽度的可靠计算,您将能够采用它。但是,如果您想要向后兼容,我提供的解决方法可能仍然是更好的选择。

我希望有所帮助!

答案 4 :(得分:0)

即使我没有时间对其进行测试,我也很确定问题是标签尺寸是根据进展来计算的。提前量是从一个角色的基点到下一个角色的移动量。通常对于斜体字体,前进可以小于边界。因此,添加预付款将缩短布局的结束。

即。 Baskerville-Italic H

(lldb) p bounds[0].size
(CGSize) $6 = (width=33.53515625, height=26.484375)
(lldb) p advances[0]
(CGSize) $7 = (width=30, height=0)

所以我认为你必须添加最后一个字符的advance和bounding框之间的区别,如果文本是理想的布局(没有压缩等等)。

要获得这两个值,您必须调用一些CT函数:

// What you probably have
CTFontRef font = …;
CFStringRef string = …;
CFAAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes);

// Get the character and glyph
CFIndex count = CFStringGetLength(string); // The length of the string
UniChar character;
CFStringGetCharacters( string, CFMakeRange( count-1, 1), &character );
CGGlyph glyph;
CTStringGetGlyphsForCharacters( font, &character, &glyph,1  );

// Get the advance
CGSize advance;
CTFontGetAdvancesForGlyphs( font, 0, &glyph, &advance, 1);

// Get the bounds
CGRect bounds;
CTFontGetAdvancesForGlyphs( font, 0, &glyph, &bounds, 1);

输入Safari。

添加:你在左侧遇到同样的问题:前进到大写L是0(第一个字符),但是边界框有一个负x。因此左侧被剪裁。在那里添加空间..(到目前为止更容易。)

答案 5 :(得分:0)

使用NSStringDrawingUsesDeviceMetrics中的boundingRectWithSize:options:context:可以获得更好的效果。

答案 6 :(得分:0)

1:使用当前选定的字体将文字设置为标签。

2:使用此方法

- (CGSize)getSizeforController:(id)view 
{
    UILabel *tempView =(UILabel *)view;
    NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
    context.minimumScaleFactor = 0.8;
    float height = tempView.frame.size.height;
    CGSize size=[tempView.text boundingRectWithSize:CGSizeMake(2000, height)options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName : tempView.font}context:context].size;
    return size;
}

3:然后设置

CGSize newSize = [self.getSizeforController:self.lblYourLabel];
self.lblYourLabel.frame.size = newSize;

希望这对你有用。

答案 7 :(得分:0)

试试这个

CGSize lableWidth = CGSizeMake(300, CGFLOAT_MAX);
CGSize requiredSize = [yourLabel sizeWithFont:[UIFont fontWithName:@"FontName" size:17] constrainedToSize:lableWidth lineBreakMode:NSLineBreakByWordWrapping];
int calculatedHeight = requiredSize.height;