Open nullLuli opened 4 years ago
自问自答,可以在traitCollectionDidChange里面调用layer的setNeedDisplay来实现
class BaseLabel: YYLabel { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) layer.setNeedsDisplay() } }
@nullLuli 这个方法好像还是不行,切换后颜色依然没有变化
https://stackoverflow.com/a/60619839/6516391
traitCollectionDidChange更改了它在iOS 13中的工作方式,如下面的鏈接所示:
https://developer.apple.com/documentation/ios_ipados_release_notes/ios_13_release_notes
因为attributedString引用了cgColor,我这边的做法是重复创建attributedString再次赋值刷新YYLabel
这个是由于在设置ForegroundColor的时候YY还一起设置了kCTForegroundColorAttributeName,这个存储的是cgcolor,而且系统在绘制的时候优先读取这个属性。 解决方案目前有两个: 前提添加
1、在- (void)setColor:(UIColor *)color range:(NSRange)range { // [self setAttribute:(id)kCTForegroundColorAttributeName value:(id)color.CGColor range:range]; [self setAttribute:NSForegroundColorAttributeName value:color range:range]; }把kCTForegroundColorAttributeName去掉。
2、直接在每模式改变需要重新绘制前把 @@kCTForegroundColorAttributeName属性 去掉。
(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection];
// 修复模式切换时由于存在老旧的kCTForegroundColorAttributeName导致动态属性失败问题 NSMutableAttributedString innerText = [self valueForKey:@"_innerText"]; [innerText enumerateAttribute:NSForegroundColorAttributeName inRange:NSMakeRange(0, innerText.length) options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(id _Nullable value, NSRange range, BOOL _Nonnull stop) { [innerText removeAttribute:(id)kCTForegroundColorAttributeName range:range]; }];
[self.layer setNeedsDisplay]; }
这个是由于在设置ForegroundColor的时候YY还一起设置了kCTForegroundColorAttributeName,这个存储的是cgcolor,而且系统在替换的时候优先转换这个属性。 解决方案目前有两个: 添加
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; [self.layer setNeedsDisplay]; }
1,在-(void)setColor:(UIColor *)颜色范围:(NSRange)range { // [self setAttribute:(id)kCTForegroundColorAttributeName value:(id)color.CGColor range:range]; [self setAttribute:NSForegroundColorAttributeName值:颜色范围:范围]; }把kCTForegroundColorAttributeName去掉。
2,直接在每模式改变需要重新放置前把@@ kCTForegroundColorAttributeName属性去掉。
- (void)traitCollectionDidChange:(UITraitCollection )previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; // //修复模式切换时由于存在老旧的kCTForegroundColorAttributeName导致动态属性失败问题 NSMutableAttributedString innerText = [self valueForKey:@“ _ innerText”]; [innerText enumerateAttribute:NSForegroundColorAttributeName inRange:NSMakeRange(0,innerText.length) 选项:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(id _Nullable value,NSRange range,BOOL * _Nonnull stop){ [innerTextNamerangeAttribute:(id }]; [self.layer setNeedsDisplay]; }
您好能分享详细代码吗 我通过这个没法实现
自问自答,可以在traitCollectionDidChange里面调用layer的setNeedDisplay来实现
类BaseLabel:YYLabel { 覆盖函数traitCollectionDidChange(_ previousTraitCollection:UITraitCollection?){ super.traitCollectionDidChange(previousTraitCollection) layer.setNeedsDisplay() } }
你确定这个方法可以实现吗 我试了是不可以了 还是还什么地方适配尼
自问自答,可以在traitCollectionDidChange里面调用layer的setNeedDisplay来实现 类BaseLabel:YYLabel { 覆盖函数traitCollectionDidChange(_ previousTraitCollection:UITraitCollection?){ super.traitCollectionDidChange(previousTraitCollection) layer.setNeedsDisplay() } }
你确定这个方法可以实现吗 我试了是不可以了 还是还什么地方适配尼
在这个方法中先判断, 然后重新渲染一遍 Attributes
, 有要调整的颜色啊, 图片啊什么的. 都处理一遍
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
// 这里还要区分是否 iOS 13 以上. 否则是之前的处理逻辑
// 首先判断
traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection)
}
这个是由于在设置ForegroundColor的时候YY还一起设置了kCTForegroundColorAttributeName,这个存储的是cgcolor,而且系统在绘制的时候优先读取这个属性。 解决方案目前有两个: 前提添加
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; [self.layer setNeedsDisplay]; }
1、在- (void)setColor:(UIColor *)color range:(NSRange)range { // [self setAttribute:(id)kCTForegroundColorAttributeName value:(id)color.CGColor range:range]; [self setAttribute:NSForegroundColorAttributeName value:color range:range]; }把kCTForegroundColorAttributeName去掉。
2、直接在每模式改变需要重新绘制前把 @@kCTForegroundColorAttributeName属性 去掉。
- (void)traitCollectionDidChange:(UITraitCollection )previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; // 修复模式切换时由于存在老旧的kCTForegroundColorAttributeName导致动态属性失败问题 NSMutableAttributedString innerText = [self valueForKey:@"_innerText"]; [innerText enumerateAttribute:NSForegroundColorAttributeName inRange:NSMakeRange(0, innerText.length) options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { [innerText removeAttribute:(id)kCTForegroundColorAttributeName range:range]; }]; [self.layer setNeedsDisplay]; }
不能直接删掉kCTForegroundColorAttributeName, 会引起其他的问题,比如斜体颜色就会丢失 比较推荐的操作是在这这个代理方法里更新kCTForegroundColorAttributeName = value
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
NSMutableAttributedString *innerText = [self valueForKey:@"_innerText"];
[innerText enumerateAttribute:NSForegroundColorAttributeName
inRange:NSMakeRange(0, innerText.length)
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
usingBlock:^(UIColor * _Nullable value, NSRange range, BOOL * _Nonnull stop) {
if (value != nil) {
innerText.yy_color = value;
}
}];
[self _setLayoutNeedUpdate];
}
}
window.overrideUserInterfaceStyle = UIUserInterfaceStyleDark 强制暗黑模式动态颜色不起作用,这个要怎么解决?
YYLabel的attributedText属性设置了后不能跟着模式的切换而变化。是不是不支持黑暗模式