iOS Dark Mode

iOS Dark Mode

参考文档:

如何适配深色模式呢?参考官方文档Supporting Dark Mode in Your Interface

1.颜色
为UI选择自适应颜色,Light和Dark界面选择不同的颜色调色板,有2中方式

  • 选择语义颜色(semantic colors)而不是固定颜色值,如使用labelColor
  • 在assets目录中定义自定义颜色
    自定义颜色

参考UI Element Colors,有如下的分类

  • Label Colors - 标签颜色
    • label
    • secondaryLabel
    • tertiaryLabel
    • quaternaryLabel
  • Standard Content Background Colors - 标准内容背景颜色
    • systemBackground - 界面主要背景的颜色
    • secondarySystemBackground
    • tertiarySystemBackground

Dark Mode: The Basics中的例子来说,在Light模式时,显示效果如下:
light
而在Dark模式下,UITabBar会自动变成Dark模式,但是UILabel就可不见了(颜色问题)
Dark
现在来修改
1.将controller的背景颜色修改为system background color,在dark模式下,显示效果如下,label可见了:

system background color
2.Dark模式下使用不同的图片
在Appearances下选择Any, Dark,社会Dark模式下的图片
图片
dark
3.通过代码设置secondaryView的背景颜色

self.secondaryView.backgroundColor = .secondarySystemBackground

代码设置背景颜色
但如果想在Light模式下,背景颜色为blue,Dark模式下,背景颜色为yellow,该如何实现呢?此时要使用动态颜色

public init(dynamicProvider: @escaping (UITraitCollection) -> UIColor)

如下:

    let dynamicColor = UIColor.init { (traitCollection) -> UIColor in
        if traitCollection.userInterfaceStyle == .dark {
            return .yellow
        } else {
            return .blue
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.secondaryView.backgroundColor = dynamicColor
    }

blueyellow

如何显示Dark Mode

Interface Builder中通过如下的选项来切换

interface builder
对于模拟器,通过如下的设置来切换
模拟器

UITraitCollection

可以使用 UITraitCollection.current 这个类属性来获取当前 App 的颜色模式。不过需要注意的是在,并不是在所有的地方使用这个 API 都是正确的,只有在下面这些方法中,才可以放心的使用这个 API:

UIViewUIViewControllerUIPresentationController
draw()
layoutSubview()viewWillLayoutSubviews() viewDidLayoutSubviews()containerViewWillLayoutSubviews() containerViewDidLayoutSubviews()
traitCollectionDidChange() tintColorDidChange()traitCollectionDidChange()traitCollectionDidChange()

看下定义:

extension UITraitCollection {

    
    /* The current trait collection, used when resolving the appearance of dynamic UIColors and similar objects.
     * This is a thread-local property, so it may be changed on non-main threads without affecting the main thread.
     */
    @available(iOS 13.0, *)
    open class var current: UITraitCollection

    
    /* Sets `UITraitCollection.currentTraitCollection` to this trait collection, performs the given actions,
     * then restores `UITraitCollection.currentTraitCollection` to its original value.
     * Just like `currentTraitCollection`, this only affects the current thread, and may be used on non-main threads
     * without affecting the main thread.
     */
    @available(iOS 13.0, *)
    open func performAsCurrent(_ actions: () -> Void)
}

可参考:

颜色

CALayerCGColor并不了解动态颜色,因此,假设有CALayer,并且需要设置其边框颜色为不能动态显示的cgColor。 那么如何解决这种颜色?

let layer = Layer()
let traitCollection = view.traitCollection

方法一:

let resolvedColor = UIColor.label.resolvedColor(with: traitCollection)
layer.borderColor = resolvedColor.cgColor

方法二:
traitCollection作为当前的trait collection
方法performAsCurrent的解释如下:

UITraitCollection.currentTraitCollection设置为这个trait collection。并执行给定的操作,然后将UITraitCollection.currentTraitCollection恢复为原始值

traitCollection.performAsCurrent { layer.borderColor = UIColor.label.cgColor }

方法三:

let savedTraitCollection = UITraitCollection.current
UITraitCollection.current = traitCollection
layer.borderColor = UIColor.label.cgColor
UITraitCollection.current = savedTraitCollection

图片

guard let image = UIImage(named: named) else { return }
let assets = image.imageAsset
guard let resolvedImage = assets?.image(with: self.traitCollection) else { return }
self.imageView.image = resolvedImage

Dark Mode: Deep Dive中的例子

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        
        super.traitCollectionDidChange(previousTraitCollection)
        
        if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
            
            //手动处理颜色
            let layer = CALayer()
            let traitCollection = view.traitCollection
            
            //1 - ask color to resolve itself
            let resolvedColor = UIColor.label.resolvedColor(with: traitCollection)
            layer.borderColor = resolvedColor.cgColor
            
            //2
            traitCollection.performAsCurrent {
                layer.borderColor = UIColor.label.cgColor
            }
            
            //3
            let savedTraitCollection = UITraitCollection.current
            UITraitCollection.current = traitCollection
            layer.borderColor = UIColor.label.cgColor
            UITraitCollection.current = savedTraitCollection
            
            //图片
            let image = UIImage(named: "sampleIMG")
            let asset = image?.imageAsset
            let resolvedImg = asset?.image(with: traitCollection)
            
        }
        
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值