YYText icon indicating copy to clipboard operation
YYText copied to clipboard

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

Open nullLuli opened this issue 5 years ago • 11 comments

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

nullLuli avatar Dec 10 '19 07:12 nullLuli

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

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

nullLuli avatar Dec 10 '19 11:12 nullLuli

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

vhrers avatar Mar 10 '20 03:03 vhrers

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

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

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

kudzaiTnexus avatar Mar 11 '20 10:03 kudzaiTnexus

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

XiFengLang avatar Mar 25 '20 06:03 XiFengLang

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

zhengziyan19 avatar Apr 03 '20 06:04 zhengziyan19

这个是由于在设置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 avatar Dec 11 '20 09:12 ZeroYoung1104

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

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

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

ZeroYoung1104 avatar Dec 11 '20 09:12 ZeroYoung1104

自问自答,可以在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)
}

wolfcon avatar Apr 01 '21 10:04 wolfcon

这个是由于在设置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 avatar Apr 11 '23 03:04 Leo2016

- (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];
    }
}

Leo2016 avatar Apr 11 '23 03:04 Leo2016

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

gisxie avatar Mar 25 '24 07:03 gisxie