ios - UILabel 在内容的左右边缘剪裁斜体(倾斜)文本(iOS 6+)

标签 ios ios7 uilabel autolayout

问题: UILabel 可能会剪裁斜体(倾斜)字符,甚至剪裁左右边缘的脚本。以下屏幕截图显示了该问题。在左边,'j' 的下降部分被剪掉;在右边缘,“l”的上升部分被剪掉了。我意识到这很微妙,并不是每个人都会关心(但是,字体越大,问题越严重)。

enter image description here

这是一个使用 Zapfino 的不太微妙的示例,尺寸为 22。请注意木星中的“j”看起来几乎像一个“i”:

enter image description here

在上面的示例中,标签的背景颜色为橙色,文本左对齐,标签保持其固有内容大小。

这是 UILabel 的默认行为,多个版本的 iOS 都是这样(所以我不期望 Apple 会修复)。

我尝试过的: 将标签的 clipsToBounds 属性设置为 NO 并不能解决问题。我还知道我可以在标签上设置固定宽度约束,以便在后缘为文本留出更多空间。但是,固定宽度约束不会为上例中的“j”提供更多空间。

我将使用利用 Auto Layout 和标签的 alignmentRectInsets 的解决方案来回答我自己的问题。

最佳答案

当文本左对齐时,顶部标签显示 UILabel 的默认行为,即标签保持其固有内容大小。底部标签是 UILabel 的一个简单(几乎是微不足道的)子类。底部标签不夹住 'j' 或 'l';相反,它为文本在左右边缘提供了一些呼吸空间,而无需居中对齐文本(糟糕)。

enter image description here

虽然标签本身并没有在屏幕上对齐,但它们的文本确实对齐了;而且,在 IB 中,标签的左边缘实际上是对齐的,因为我重写了 UILabel 子类中的 alignmentRectInsets

enter image description here

这是配置两个标签的代码:

#import "ViewController.h"
#import "NonClippingLabel.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *topLabel;
@property (weak, nonatomic) IBOutlet NonClippingLabel *bottomLabel;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *string = @"jupiter ariel";

    UIFont *font = [UIFont fontWithName:@"Helvetica-BoldOblique" size:28];

    NSDictionary *attributes = @{NSFontAttributeName: font};

    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:attributes];

    self.topLabel.attributedText = attrString;
    self.bottomLabel.attributedText = attrString;     
}

下面是 NonClippingLabel 子类的实现:

#import <UIKit/UIKit.h>

@interface NonClippingLabel : UILabel

@end

@implementation NonClippingLabel

#define GUTTER 4.0f // make this large enough to accommodate the largest font in your app

- (void)drawRect:(CGRect)rect
{
    // fixes word wrapping issue
    CGRect newRect = rect;
    newRect.origin.x = rect.origin.x + GUTTER;
    newRect.size.width = rect.size.width - 2 * GUTTER;
    [self.attributedText drawInRect:newRect];
}

- (UIEdgeInsets)alignmentRectInsets
{
    return UIEdgeInsetsMake(0, GUTTER, 0, GUTTER);
}

- (CGSize)intrinsicContentSize
{
    CGSize size = [super intrinsicContentSize];
    size.width += 2 * GUTTER;
    return size;
}

@end

无需编辑字体文件,无需使用 Core Text;对于那些使用 iOS 6+ 和自动布局的用户来说,这只是一个相对简单的 UILabel 子类。

更新:

Augie 注意到我原来的解决方案阻止了多行文本的自动换行。我通过使用 drawInRect: 而不是 drawAtPoint: 在标签的 drawRect: 方法中绘制文本来解决这个问题。

截图如下:

enter image description here

顶部标签是一个普通的 UILabel。底部标签是一个 NonClippingLabel,具有极端的间距设置以适应尺寸为 22.0 的 Zapfino。两个标签都使用自动布局左右对齐。

enter image description here

关于ios - UILabel 在内容的左右边缘剪裁斜体(倾斜)文本(iOS 6+),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20985085/

相关文章:

iOS:将单词置于 UILabel 内句子中心的算法

ios - 如何在 Swift 中格式化本地化字符串?

ios - 执行选择器警告 vs dispatch _async

ios - UIPageViewController subview Controller 之间的水平填充

ios - UILabel 不会在 UIView 中居中

iphone - 为什么我的文字在我的 ios 应用程序中看起来如此糟糕?

ios - 在导航 Controller 中禁用 View Controller 的旋转

ios - 如何在 Swift 的 View 层次结构顶部添加 View ?

ios - Apple PushNotification : Need Server Side functionality Guide

ios - xcode 屏幕大小是固定的 - 每个设备都不会改变