UILabel обрезает курсивный (наклонный) текст в левом и правом краях содержимого (iOS 6+)

Проблема: UILabel может обрезать курсивные (наклонные) символы и даже скрипты на левом и правом краях. На следующем снимке экрана отображается проблема. На левом краю сжимается символ "j" ; на правом краю, подрезка 'l' обрезается. Я понимаю, что это тонко, и не все заботятся (однако проблема ухудшается при больших размерах шрифтов).

enter image description here

Здесь менее тонкий пример с использованием Zapfino, размер 22. Обратите внимание, что "j" в jupiter выглядит почти как "i":

enter image description here

В приведенных выше примерах цвет фона ярлыка оранжевый, текст выравнивается по левому краю, а этикетка сохраняет свой собственный размер содержимого.

Это поведение по умолчанию для UILabel по умолчанию, и оно было таким образом для нескольких версий iOS (поэтому я не ожидал исправления от Apple).

Что я пробовал: Установка свойства label clipsToBounds на NO не устраняет проблему. Я также знаю, что я могу установить ограничение на фиксированную ширину на ярлыке, чтобы придать тексту больше места на заднем фронте. Однако ограничение фиксированной ширины не дало бы "j" в приведенном выше примере больше места.

Я собираюсь ответить на свой вопрос, используя решение, которое использует автоматический макет и метку alignmentRectInsets.

Ответы

Ответ 1

Верхняя метка показывает поведение по умолчанию UILabel по умолчанию, когда текст выравнивается влево, чтобы метка сохраняла свой собственный размер содержимого. Нижняя метка - простой (почти тривиальный) подкласс UILabel. Нижняя метка не зажимает "j" или "l"; вместо этого он дает текст в какой-то комнате дышать на левом и правом краях без выравнивания по центру текста (yuck).

enter image description here

Хотя сами ярлыки не отображаются на экране, их текст выглядит выравниваемым; и что еще, в IB, наклейки фактически имеют выровненные левые ребра, потому что я переопределяю alignmentRectInsets в подклассе UILabel.

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

Нет редактирования файла шрифта, без использования основного текста; просто относительно простой подкласс UILabel для тех, кто использует iOS 6+ и Auto Layout.

Update:

Оги понял, что мое оригинальное решение предотвратило перенос слов для многострочного текста. Я исправил эту проблему, используя drawInRect: вместо drawAtPoint:, чтобы нарисовать текст в методе drawRect:.

Вот скриншот:

enter image description here

Верхняя метка - простой ваниль UILabel. Нижняя метка NonClippingLabel с экстремальной настройкой желоба для размещения Zapfino размером 22.0. Обе метки выравниваются влево и вправо с помощью автоматической компоновки.

enter image description here