ibireme / YYText

Powerful text framework for iOS to display and edit rich text.
MIT License
8.84k stars 1.68k forks source link

可以进行iOS13黑暗模式适配吗 #911

Open nullLuli opened 4 years ago

nullLuli commented 4 years ago

YYLabel的attributedText属性设置了后不能跟着模式的切换而变化。是不是不支持黑暗模式

nullLuli commented 4 years ago

自问自答,可以在traitCollectionDidChange里面调用layer的setNeedDisplay来实现

class BaseLabel: YYLabel { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) layer.setNeedsDisplay() } }

vhrers commented 4 years ago

@nullLuli 这个方法好像还是不行,切换后颜色依然没有变化

kudzaiTnexus commented 4 years ago

https://stackoverflow.com/a/60619839/6516391

traitCollectionDidChange更改了它在iOS 13中的工作方式,如下面的鏈接所示:

https://developer.apple.com/documentation/ios_ipados_release_notes/ios_13_release_notes

XiFengLang commented 4 years ago

因为attributedString引用了cgColor,我这边的做法是重复创建attributedString再次赋值刷新YYLabel

zhengziyan19 commented 4 years ago

这个是由于在设置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属性 去掉。

ZeroYoung1104 commented 3 years ago

这个是由于在设置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]; }

您好能分享详细代码吗 我通过这个没法实现

ZeroYoung1104 commented 3 years ago

自问自答,可以在traitCollectionDidChange里面调用layer的setNeedDisplay来实现

类BaseLabel:YYLabel { 覆盖函数traitCollectionDidChange(_ previousTraitCollection:UITraitCollection?){ super.traitCollectionDidChange(previousTraitCollection) layer.setNeedsDisplay() } }

你确定这个方法可以实现吗 我试了是不可以了 还是还什么地方适配尼

wolfcon commented 3 years ago

自问自答,可以在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)
}
Leo2016 commented 1 year ago

这个是由于在设置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

Leo2016 commented 1 year ago
- (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];
    }
}
gisxie commented 4 months ago

window.overrideUserInterfaceStyle = UIUserInterfaceStyleDark 强制暗黑模式动态颜色不起作用,这个要怎么解决?