-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathSSDynamicButton.m
More file actions
139 lines (104 loc) · 4.39 KB
/
SSDynamicButton.m
File metadata and controls
139 lines (104 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//
// SSDynamicButton.m
// SSDynamicText
//
// Created by Adam Grzegorowski on 18/07/15.
// Copyright (c) 2015 Splinesoft. All rights reserved.
//
#import "SSDynamicButton.h"
#import "UIApplication+SSTextSize.h"
#import "UIView+SSTextSize.h"
#import "NSAttributedString+SSTextSize.h"
@interface SSDynamicButton ()
@property (nonatomic, strong) NSMutableDictionary *baseAttributedTitlesDictionary;
@end
@implementation SSDynamicButton
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
NSAssert(self.buttonType == UIButtonTypeCustom, @"Change SSDynamicButton.buttonType to UIButtonTypeCustom in your nib");
[self setupDefaultFontDescriptorBasedOnFont:self.titleLabel.font];
[self setup];
}
+ (instancetype)buttonWithFont:(NSString *)fontName baseSize:(CGFloat)size {
UIFontDescriptor *fontDescriptor = [UIFontDescriptor fontDescriptorWithName:fontName size:size];
return [self buttonWithFontDescriptor:fontDescriptor];
}
+ (instancetype)buttonWithFontDescriptor:(UIFontDescriptor *)descriptor {
SSDynamicButton *button = [self new];
button.defaultFontDescriptor = descriptor;
return button;
}
- (void)dealloc {
[self ss_stopObservingTextSizeChanges];
[self removeTitleLabelFontObserver];
}
- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state {
NSNumber *key = @(state);
if (title) {
[self.baseAttributedTitlesDictionary setObject:title forKey:key];
} else {
[self.baseAttributedTitlesDictionary removeObjectForKey:key];
}
[self changeAttributedTitle:title forState:state withFontSizeDelta:[UIApplication sharedApplication].preferredFontSizeDelta];
}
#pragma mark - Private methods
- (void)setup {
__weak typeof(self) weakSelf = self;
[self addTitleLabelFontObserver];
SSTextSizeChangedBlock changeHandler = ^(NSInteger newDelta) {
[weakSelf changeFontWithDelta:newDelta];
[weakSelf changeAttributedStringWithDelta:newDelta];
};
[self ss_startObservingTextSizeChangesWithBlock:changeHandler];
}
- (void)changeFontWithDelta:(NSInteger)newDelta {
CGFloat preferredSize = [self.defaultFontDescriptor.fontAttributes[UIFontDescriptorSizeAttribute] floatValue];
preferredSize += newDelta;
[self removeTitleLabelFontObserver];
self.titleLabel.font = [UIFont fontWithDescriptor:self.defaultFontDescriptor
size:preferredSize];
[self addTitleLabelFontObserver];
}
- (void)changeAttributedTitle:(NSAttributedString *)attributedTitle forState:(UIControlState)state withFontSizeDelta:(NSInteger)newDelta {
[super setAttributedTitle:[attributedTitle ss_attributedStringWithAdjustedFontSizeWithDelta:newDelta] forState:state];
}
- (void)changeAttributedStringWithDelta:(NSInteger)newDelta {
[self.baseAttributedTitlesDictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSAttributedString *title, BOOL *stop) {
[self changeAttributedTitle:title forState:key.unsignedIntegerValue withFontSizeDelta:newDelta];
}];
}
#pragma mark - Accessors
- (NSMutableDictionary *)baseAttributedTitlesDictionary {
if (_baseAttributedTitlesDictionary == nil) {
_baseAttributedTitlesDictionary = [NSMutableDictionary dictionary];
}
return _baseAttributedTitlesDictionary;
}
#pragma mark - Font observing
- (void)addTitleLabelFontObserver {
#if !TARGET_INTERFACE_BUILDER
[self.titleLabel addObserver:self forKeyPath:NSStringFromSelector(@selector(font)) options:NSKeyValueObservingOptionNew context:NULL];
#endif
}
- (void)removeTitleLabelFontObserver {
#if !TARGET_INTERFACE_BUILDER
[self.titleLabel removeObserver:self forKeyPath:NSStringFromSelector(@selector(font))];
#endif
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(font))]) {
NSInteger newDelta = [UIApplication sharedApplication].preferredFontSizeDelta;
[self setupDefaultFontDescriptorBasedOnFont:self.titleLabel.font];
[self changeFontWithDelta:newDelta];
[self changeAttributedStringWithDelta:newDelta];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
@end