UIAppearance не действует на UILabels, созданный программно
Мы расширили UILabel, чтобы иметь возможность применять стандартные шрифты и цвета для всех видов использования данного типа меток в наших приложениях. Например.
@interface UILabelHeadingBold : UILabel
@end
В нашем приложении AppDelegate мы применяем шрифты и цвета, подобные этому
[[UILabelHeadingBold appearance] setTextColor:<some color>];
[[UILabelHeadingBold appearance] setFont:<some font>];
При добавлении UILabel в наши XIB мы теперь можем выбрать класс типа UILabelHeadingBold, и он работает так, как ожидалось. Метка отображается с правильным шрифтом и цветом, как указано в нашем AppDelegate.
Однако, если мы создаем метку программно, например.
UILabelHeadingBold *headingLabel = [[UILabelHeadingBold alloc] initWithFrame:CGRectMake(10, 10, 100, 30)];
[self.mainView addSubview:headingLabel];
UILabel не получает ожидаемый шрифт/цвет. Мы должны вручную применить эти атрибуты.
Есть ли способ заставить UIAppearance вступить в силу для программно созданных элементов пользовательского интерфейса или работает только при использовании в XIB?
Ответы
Ответ 1
Из документации Apple:
Чтобы поддерживать настройку внешнего вида, класс должен соответствовать Протокол UIAppearanceContainer и соответствующие методы доступа должны быть помечены знаком UI_APPEARANCE_SELECTOR.
Например, в UINavigationBar.h
, tintColor
помечено UI_APPEARANCE_SELECTOR
@property(nonatomic,retain) UIColor *tintColor UI_APPEARANCE_SELECTOR;
Но в UILabel.h вы можете видеть, что свойства textColor
и font
не помечены с помощью UI_APPEARANCE_SELECTOR, но как-то он работает при добавлении в Interface Builder (в соответствии с документацией он вообще не должен работать).
Ответ 2
Простой хак, который работает для меня без проблем, - это создание категории с установщиком UIAppearance, который изменяет свойства UILabel.
Следуя соглашениям UIAppearance, я создал метод:
- (void)setTextAttributes:(NSDictionary *)numberTextAttributes;
{
UIFont *font = [numberTextAttributes objectForKey:UITextAttributeFont];
if (font) {
self.font = font;
}
UIColor *textColor = [numberTextAttributes objectForKey:UITextAttributeTextColor];
if (textColor) {
self.textColor = textColor;
}
UIColor *textShadowColor = [numberTextAttributes objectForKey:UITextAttributeTextShadowColor];
if (textShadowColor) {
self.shadowColor = textShadowColor;
}
NSValue *shadowOffsetValue = [numberTextAttributes objectForKey:UITextAttributeTextShadowOffset];
if (shadowOffsetValue) {
UIOffset shadowOffset = [shadowOffsetValue UIOffsetValue];
self.shadowOffset = CGSizeMake(shadowOffset.horizontal, shadowOffset.vertical);
}
}
В категории UILabel:
@interface UILabel (UISS)
- (void)setTextAttributes:(NSDictionary *)numberTextAttributes UI_APPEARANCE_SELECTOR;
@end
Я все еще пытаюсь понять, почему оригинальный сеттер не работает.
Ответ 3
Решение @robert.wijas отлично работает!
Для iOS 7 и выше мне пришлось обновить ключ, так как тот, который он использовал, устарел для 7+:
- (void)setTextAttributes:(NSDictionary *)numberTextAttributes;
{
UIFont *font = [numberTextAttributes objectForKey:NSFontAttributeName];
if (font) {
self.font = font;
}
UIColor *textColor = [numberTextAttributes objectForKey:NSForegroundColorAttributeName];
if (textColor) {
self.textColor = textColor;
}
UIColor *textShadowColor = [numberTextAttributes objectForKey:NSShadowAttributeName];
if (textShadowColor) {
self.shadowColor = textShadowColor;
}
NSValue *shadowOffsetValue = [numberTextAttributes objectForKey:NSShadowAttributeName];
if (shadowOffsetValue) {
UIOffset shadowOffset = [shadowOffsetValue UIOffsetValue];
self.shadowOffset = CGSizeMake(shadowOffset.horizontal, shadowOffset.vertical);
}
}
Ответ 4
Обходной путь, который я использовал, состоит в том, чтобы вручную применить цвет из установленного внешнего вида:
let label = UILabel()
label.textColor = UILabel.appearance().textColor
Таким образом, вам не нужно ссылаться на что-то новое или явно определять цвет. Это также работает для контекстно-зависимой окраски:
label.textColor = UILabel.appearance(whenContainedInInstancesOf:[MyView.self]).textColor
Ответ 5
У меня была точно такая же проблема, но в Свифте. Пользовательский UILabel
вид UILabel
будет работать, если он будет добавлен из раскадровки, но не будет добавлен из кода.
Вот решение, которое я нашел в Swift, которое работает для меня:
class MyLabel: UILabel { }
extension UILabel {
@objc dynamic var customFont: UIFont! {
get { return self.font }
set { self.font = newValue }
}
@objc dynamic var customColor: UIColor! {
get { return self.textColor }
set { self.textColor = newValue }
}
}
Затем добавьте эти строки, где вы настраиваете внешний вид вашего приложения:
MyLabel.appearance().customFont = UIFont.systemFont(ofSize: 20)
MyLabel.appearance().customColor = UIColor.magenta