Читать книгу iOS. Приемы программирования - Вандад Нахавандипур - Страница 47
Глава 1. Реализация контроллеров и видов
1.26. Создание и отображение текстов с оформлением
ОглавлениеПостановка задачи
Требуется возможность отображать в элементах вашего пользовательского интерфейса насыщенный форматированный текст, избегая при этом необходимости создавать отдельный компонент пользовательского интерфейса для каждого атрибута. Например, может потребоваться отобразить в UILabel предложение, в котором всего одно слово записано полужирным шрифтом.
Решение
Создайте экземпляр класса NSAttributedString или его изменяемого варианта, NSMutableAttributedString, и либо задайте его как текст компонента пользовательского интерфейса (например, как текст подписи UILabel) с помощью специального строкового свойства, снабженного атрибутами, либо просто воспользуйтесь встроенными методами атрибутированной строки для отрисовки текста на холсте.
Обсуждение
О насыщенном тексте слагают легенды. Многим из наших коллег-программистов приходилось сталкиваться с необходимостью отображения в пользовательском интерфейсе такой текстовой строки, в которой применяется сразу несколько видов форматирования. Например, в одной строке может понадобиться одновременно вывести и обычный текст, и курсив, причем курсивом будет записано всего одно слово. Возможно, одно из слов в предложении потребуется подчеркнуть. Для этого некоторые пытаются использовать веб-виды (Web Views), но это решение не является оптимальным, поскольку веб-виды довольно медленно отображают свой контент и неизбежно негативно воздействуют на производительность приложения. В iOS 7 можно приступать к применению атрибутированных строк. Не знаю, почему Apple решила внедрить такую возможность в iOS только сейчас, ведь Mac-разработчики пользуются атрибутированными строками уже довольно давно.
Прежде чем приступить к основной части раздела, я хотел бы четко пояснить, что понимается под термином «атрибутированная строка». Взгляните на рис. 1.69. Мы собираемся написать программу, которая будет достигать именно такого эффекта.
Рис. 1.69. Атрибутированная строка отображена на экране в простой подписи
Необходимо отметить, что этот текст отображается в одном экземпляре класса UILabel.
Итак, что мы видим в этом примере? Перечислю.
• Текст iOS имеет следующие атрибуты:
• полужирный шрифт размером 60 точек;
• черный цвет фона;
• красный цвет шрифта.
• Текст SDK имеет следующие атрибуты:
• полужирный шрифт размером 60 точек;
• белый цвет шрифта;
• светло-серую тень;
• красный цвет фона.
Удобнее всего создавать атрибутированные строки с помощью метода initWithString:, относящегося к изменяемому классу NSMutableAttributedString, и передавать этому методу экземпляр NSString. Так создается атрибутированная строка без каких-либо атрибутов. Затем, чтобы присвоить атрибуты различным частям строки, мы воспользуемся методом setAttributes: range: класса NSMutableAttributedString. Этот метод принимает два параметра:
• setAttributes – словарь, ключи которого являются символьными атрибутами и значение каждого ключа зависит от самого ключа. Вот наиболее важные ключи, которые можно задать в этом словаре:
• NSFontAttributeName – значение этого ключа является экземпляром UIFont и определяет шрифт для того или иного фрагмента строки;
• NSForegroundColorAttributeName – значение этого ключа относится к типу UIColor и определяет цвет шрифта определенного фрагмента строки;
• NSBackgroundColorAttributeName – значение этого ключа относится к типу UIColor и определяет цвет фона, на котором будет отрисовываться определенный фрагмент строки;
• NSShadowAttributeName – значение этого ключа должно быть экземпляром NSShadow и задавать тень, которую будет отбрасывать определенный фрагмент строки;
• range – значение типа NSRange, определяющее начальную точку и длину группы символов, к которой вы хотите применить указанные атрибуты.
Чтобы просмотреть все ключи, которые можно передавать этому методу, просто изучите онлайновую документацию Apple по классу NSMutableAttributedString. Я не буду помещать здесь ссылку на документацию, так как Apple может рано или поздно изменить эту ссылку, а вот поиск вас точно не подведет.
Разобьем наш пример на два словаря с атрибутами. Словарь атрибутов для слова iOS создается в коде таким образом:
NSDictionary *attributesForFirstWord = @{
NSFontAttributeName: [UIFont boldSystemFontOfSize:60.0f],
NSForegroundColorAttributeName: [UIColor redColor],
NSBackgroundColorAttributeName: [UIColor blackColor]
};
А слово SDK создается с помощью следующих атрибутов:
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor darkGrayColor];
shadow.shadowOffset = CGSizeMake(4.0f, 4.0f);
NSDictionary *attributesForSecondWord = @{
NSFontAttributeName: [UIFont boldSystemFontOfSize:60.0f],
NSForegroundColorAttributeName: [UIColor whiteColor],
NSBackgroundColorAttributeName: [UIColor redColor],
NSShadowAttributeName: shadow
};
Собрав все вместе, получаем следующий код, который не только создает нашу подпись, но и задает для нее атрибутированный текст:
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UILabel *label;
@end
@implementation ViewController
– (NSAttributedString *) attributedText{
NSString *string = @"iOS SDK";
NSMutableAttributedString *result = [[NSMutableAttributedString alloc]
initWithString: string];
NSDictionary *attributesForFirstWord = @{
NSFontAttributeName: [UIFont boldSystemFontOfSize:60.0f],
NSForegroundColorAttributeName: [UIColor redColor],
NSBackgroundColorAttributeName: [UIColor blackColor]
};
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor darkGrayColor];
shadow.shadowOffset = CGSizeMake(4.0f, 4.0f);
NSDictionary *attributesForSecondWord = @{
NSFontAttributeName: [UIFont boldSystemFontOfSize:60.0f],
NSForegroundColorAttributeName: [UIColor whiteColor],
NSBackgroundColorAttributeName: [UIColor redColor],
NSShadowAttributeName: shadow
};
/* Находим фрагмент iOS в целой строке и задаем атрибуты для этого фрагмента */
[result setAttributes: attributesForFirstWord
range: [string rangeOfString:@"iOS"]];
/* Делаем то же самое со строкой SDK */
[result setAttributes: attributesForSecondWord
range: [string rangeOfString:@"SDK"]];
return [[NSAttributedString alloc] initWithAttributedString: result];
}
– (void)viewDidLoad{
[super viewDidLoad];
self.label = [[UILabel alloc] init];
self.label.backgroundColor = [UIColor clearColor];
self.label.attributedText = [self attributedText];
[self.label sizeToFit];
self.label.center = self.view.center;
[self.view addSubview: self.label];
}
@end
См. также
Разделы 1.17 и 1.18.