Swift:暗黑模式iOS 13以上支持是否跟隨系統(tǒng)和iOS13以下的主題適配

暗黑模式

JKSwiftExtensionJKDarkModeUtilJKThemeProvider 有源碼

  • 目錄:
    • 1咬摇、暗黑模式介紹
    • 2管削、暗黑模式的關(guān)閉和打開
    • 3扒秸、iOS 13 暗黑模式的適配 (重點看)
    • 4愿汰、iOS 13 以下主題的適配:淺色和深色 (重點看)
    • 5桥狡、一次適配不完的問題
一恒界、暗黑模式的介紹
  • 1.1烟阐、暗黑模式的簡介
    從 iOS 13.0 版本開始辣卒,用戶可以選擇采用系統(tǒng)范圍內(nèi)的淺色或深色外觀墓卦。 深色外觀(稱為暗黑模式DarkMode)實現(xiàn)了許多應(yīng)用程序已經(jīng)采用的界面樣式倦春。 用戶可以選擇自己喜歡的美學,也可以選擇根據(jù)環(huán)境照明條件或特定時間表來切換其界面落剪。


    所有應(yīng)用程序都應(yīng)該支持淺色和深色界面樣式睁本,但在某些地方的特定外觀可能會表現(xiàn)更好。例如著榴,您可能總是為印刷內(nèi)容采用輕巧的外觀添履。
    在更改代碼之前,請打開黑暗模式脑又,看看應(yīng)用程序的反應(yīng)暮胧。系統(tǒng)為您做了很多工作,如果您的應(yīng)用程序使用標準視圖和控件问麸,您可能不需要進行許多更改往衷。標準視圖和控件會自動更新其外觀,以匹配當前界面樣式严卖。如果您已經(jīng)使用顏色和圖像資產(chǎn)席舍,您可以在不更改代碼的情況下添加深色變體。

  • 1.2哮笆、UITraitCollection介紹
    在 iOS 13 中来颤,我們可以通過 UITraitCollection 來判斷當前系統(tǒng)的模式。UIView 和 UIViewController 稠肘、UIScreen福铅、UIWindow 都已經(jīng)遵從了UITraitEnvironment 這個協(xié)議,因此這些類都擁有一個叫做 traitCollection 的屬性项阴,在這些類中滑黔,我們可以這樣去判斷當前 App 的顏色模式:

    let isDark = self.traitCollection.userInterfaceStyle == .dark
    
  • 1.3、模擬器暗黑模式切換的快捷鍵:command+shift+A

二、暗黑模式的關(guān)閉和打開

  • 2.1略荡、自己的app還沒有適配暗黑模式又擔心用戶使用暗黑模式的時候界面不好看:關(guān)閉暗黑模式

    • 方式一:暫時全局關(guān)閉暗黑模式:
      Info.plist 文件中庵佣,添加 key 為 UIUserInterfaceStyle,類型為 String汛兜,value 設(shè)置為 Light 即可

      Info.plist關(guān)閉暗黑模式

    • 方式二:使用代碼的方式
      強制關(guān)閉暗黑模式

      if #available(iOS 13.0,*) {
         UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.overrideUserInterfaceStyle = .light
      }
      
  • 2.2巴粪、單個頁面關(guān)閉暗黑模式

    self.overrideUserInterfaceStyle = .light
    

    提示:設(shè)置此屬性會影響當前 view/viewController/window 以及它下面的任何內(nèi)容

    如果你希望一個子視圖監(jiān)聽系統(tǒng)的模式,請將 overrideUserInterfaceStyle 屬性設(shè)置為unspecified

    self.overrideUserInterfaceStyle = .unspecified
    
三粥谬、iOS 13 暗黑模式的適配
  • 3.1验毡、iOS 13的暗黑模式我們主要分為:跟隨系統(tǒng)模式自定義模式

    • 跟隨系統(tǒng),需要設(shè)置:

      UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.overrideUserInterfaceStyle = .unspecified
      
    • 不跟隨系統(tǒng)
      淺色:UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.overrideUserInterfaceStyle = .light
      深色:UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.overrideUserInterfaceStyle = .dark

  • 3.2帝嗡、iOS 13的暗黑模式適配代碼在:JKDarkModeUtil 里面晶通,默認是 跟隨系統(tǒng)模式,主要代碼如下

    import UIKit
    
    public class JKDarkModeUtil {
      
        /// 跟隨系統(tǒng)的key
        private static let JKDarkToSystem = "JKDarkToSystem"
        /// 是否淺色模式的key
        private static let JKLightDark = "JKLightDark"
        /// 是否淺色
        public static var isLight: Bool {
            if let value = UserDefaults.jk.userDefaultsGetValue(key: JKLightDark) as? Bool {
                return value
            }
            return true
        }
        /// 是否跟隨系統(tǒng)
        public static var isFloorSystem: Bool {
            if #available(iOS 13, *) {
                if let value = UserDefaults.jk.userDefaultsGetValue(key: JKDarkToSystem) as? Bool {
                    return value
                }
                return true
            }
            return false
        }
    }
    
    // MARK:- 方法的調(diào)用
    extension JKDarkModeUtil: JKThemeable {
        public func apply() {}
    }
    
    public extension JKDarkModeUtil {
      
        // MARK: 初始化的調(diào)用
        /// 默認設(shè)置
        static func defaultDark() {
            if #available(iOS 13.0, *) {
                // 默認跟隨系統(tǒng)暗黑模式開啟監(jiān)聽
                if (JKDarkModeUtil.isFloorSystem) {
                    JKDarkModeUtil.setDarkModeFollowSystem(isFollowSystem: true)
                } else {
                    UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.overrideUserInterfaceStyle = JKDarkModeUtil.isLight ? .light : .dark
                }
            }
        }
      
        // MARK: 設(shè)置系統(tǒng)是否跟隨
        static func setDarkModeFollowSystem(isFollowSystem: Bool) {
            if #available(iOS 13.0, *) {
                // 1.1哟玷、設(shè)置是否跟隨系統(tǒng)
                UserDefaults.jk.userDefaultsSetValue(value: isFollowSystem, key: JKDarkToSystem)
                let result = UITraitCollection.current.userInterfaceStyle == .light ? true : false
                UserDefaults.jk.userDefaultsSetValue(value: result, key: JKLightDark)
                // 1.2狮辽、設(shè)置模式的保存
                if isFollowSystem {
                    UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.overrideUserInterfaceStyle = .unspecified
                } else {
                    UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.overrideUserInterfaceStyle = UITraitCollection.current.userInterfaceStyle
                }
            }
        }
      
        // MARK: 設(shè)置:淺色 / 深色
        static func setDarkModeCustom(isLight: Bool) {
            if #available(iOS 13.0, *) {
                // 1.1、只要設(shè)置了模式:就是黑或者白
                UIApplication.shared.windows.filter({$0.isKeyWindow}).first?.overrideUserInterfaceStyle = isLight ? .light : .dark
                // 1.2巢寡、設(shè)置跟隨系統(tǒng):否
                UserDefaults.jk.userDefaultsSetValue(value: false, key: JKDarkToSystem)
                UserDefaults.jk.userDefaultsSetValue(value: isLight, key: JKLightDark)
            } else {
                // 模式存儲
                UserDefaults.jk.userDefaultsSetValue(value: isLight, key: JKLightDark)
                // 通知模式更新
                LegacyThemeProvider.shared.updateTheme()
            }
        }
    }
    
    // MARK:- 動態(tài)顏色的使用
    public extension JKDarkModeUtil {
        static func colorLightDark(light: UIColor, dark: UIColor) -> UIColor {
            if #available(iOS 13.0, *) {
                return UIColor { (traitCollection) -> UIColor in
                    if JKDarkModeUtil.isFloorSystem {
                        if traitCollection.userInterfaceStyle == .light {
                            return light
                        } else {
                            return dark
                        }
                    } else {
                        return JKDarkModeUtil.isLight ? light : dark
                    }
                }
            } else {
                // iOS 13 以下主題色的使用
                if JKDarkModeUtil.isLight {
                    return light
                }
                return dark
            }
        }
    }
    
    // MARK:- 動態(tài)圖片的使用
    public extension JKDarkModeUtil {
    
        // MARK: 深色圖片和淺色圖片切換 (深色模式適配)
        /// 深色圖片和淺色圖片切換 (深色模式適配)
        /// - Parameters:
        ///   - light: 淺色圖片
        ///   - dark: 深色圖片
        /// - Returns: 最終圖片
        static func image(light: UIImage?, dark: UIImage?) -> UIImage? {
            if #available(iOS 13.0, *) {
                guard let weakLight = light, let weakDark = dark, let config = weakLight.configuration else { return light }
                let lightImage = weakLight.withConfiguration(config.withTraitCollection(UITraitCollection.init(userInterfaceStyle: UIUserInterfaceStyle.light)))
                lightImage.imageAsset?.register(weakDark, with: config.withTraitCollection(UITraitCollection(userInterfaceStyle: UIUserInterfaceStyle.dark)))
                return lightImage.imageAsset?.image(with: UITraitCollection.current) ?? light
            } else {
                // iOS 13 以下主題色的使用
                if JKDarkModeUtil.isLight {
                    return light
                }
                return dark
            }
        }
    }
    
  • 3.3喉脖、UIColor 顏色的使用方式

    JKDarkModeUtil.colorLightDark(light: UIColor.yellow, dark: UIColor.green)
    

    提示:建議自定義業(yè)務(wù)色,如下

    // MARK:- 業(yè)務(wù)顏色的使用
    extension UIColor {
        /// 背景色
        private(set) static var cA1 = JKDarkModeUtil.colorLightDark(light: UIColor.yellow, dark: UIColor.green)
    }
    

    使用:self.view.backgroundColor = .cA1

  • 3.4抑月、CGColor 適配树叽,實現(xiàn) traitCollectionDidChange 方法,適配顏色即可

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        // cgColor 顏色適配
        button.layer.borderColor = JKDarkModeUtil.colorLightDark(light: .green, dark: .brown).cgColor
    }
    

    提示: 完整的觸發(fā)方法文檔

  • 3.5谦絮、暗黑模式圖片的使用(選擇:Any,Dark)

    • Assets中添加圖片


      暗黑模式圖片的使用
    • 代碼適配圖片

      // MARK:- 動態(tài)圖片的使用(網(wǎng)絡(luò)圖片一樣)
      public extension JKDarkModeUtil {
      
          // MARK: 深色圖片和淺色圖片切換 (深色模式適配)
          /// 深色圖片和淺色圖片切換 (深色模式適配)
          /// - Parameters:
          ///   - light: 淺色圖片
          ///   - dark: 深色圖片
          /// - Returns: 最終圖片
          static func image(light: UIImage?, dark: UIImage?) -> UIImage? {
               if #available(iOS 13.0, *) {
                  guard let weakLight = light, let weakDark = dark, let config = weakLight.configuration else { return light }
                  let lightImage = weakLight.withConfiguration(config.withTraitCollection(UITraitCollection.init(userInterfaceStyle: UIUserInterfaceStyle.light)))
                  lightImage.imageAsset?.register(weakDark, with: config.withTraitCollection(UITraitCollection(userInterfaceStyle: UIUserInterfaceStyle.dark)))
                  return lightImage.imageAsset?.image(with: UITraitCollection.current) ?? light
               } else {
                  // iOS 13 以下主題色的使用
                  if JKDarkModeUtil.isLight {
                     return light
                  }
                  return dark
               }
         }
      }
      
      • 提示:代碼適配的時候需要在:traitCollectionDidChange 方法里面再次賦值题诵,iOS 13 以上的建議直接再 Assets中添加圖片
        如果是 cell 里面的圖直接使用方法加載圖片,刷新一下視圖即可
四层皱、iOS 13 以下主題的適配:淺色和深色
  • 4.1性锭、iOS 13 以下我們采用的是監(jiān)聽模式來改變主題色,源碼在 JKThemeProvider叫胖,使用步驟如下

    • 1>草冈、遵守協(xié)議 JKThemeable (遵守UITraitEnvironment協(xié)議的均可使用)

      extension ViewController: JKThemeable {
          func apply() {
             self.view.backgroundColor = JKDarkModeUtil.colorLightDark(light: UIColor.yellow, dark: UIColor.green)
          }
      }
      
    • 2>、注冊監(jiān)聽模式變化

       themeProvider.register(observer: self)
      
    • 3>瓮增、模式變化通知

      JKDarkModeUtil.setDarkModeCustom(isLight: true) 
      
  • 4.2怎棱、顏色的調(diào)用和圖片模式的調(diào)用和iOS13一樣

    • 顏色調(diào)用

      JKDarkModeUtil.colorLightDark(light: UIColor.yellow, dark: UIColor.green)
      
    • 圖片調(diào)用

      JKDarkModeUtil.image(light: UIImage(named: "tabbar_profile"), dark: UIImage(named: "tabbar_profile_selected"))
      
  • 4.3、主題變化后會走代理 apply()绷跑,在代理方法里面我們只需要重新調(diào)用顏色或者圖片的方法即可

    extension ViewController: JKThemeable {
        func apply() {
            self.view.backgroundColor = JKDarkModeUtil.colorLightDark(light: UIColor.yellow, dark: UIColor.green)
            darkImageView.image = JKDarkModeUtil.image(light: UIImage(named: "tabbar_profile"), dark: UIImage(named: "tabbar_profile_selected"))
        }
    }
    
五拳恋、一次適配不完的問題
  • 5.1、一次適配不完的問題你踩,我們在使用JKDarkModeUtil 調(diào)用一些方法的時候诅岩,適配哪里就哪里使用即可,不使用的就按照之前的顏色以及圖片調(diào)用即可
  • 5.2带膜、提示:在使用 JKDarkModeUtilJKThemeProvider 的時候吩谦,需要在設(shè)置 windowrootViewController 后需要調(diào)用 JKDarkModeUtil.defaultDark()
如果能幫到您,請在 JKSwiftExtension 給個星星膝藕,謝謝
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末式廷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子芭挽,更是在濱河造成了極大的恐慌滑废,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袜爪,死亡現(xiàn)場離奇詭異蠕趁,居然都是意外死亡,警方通過查閱死者的電腦和手機辛馆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門俺陋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昙篙,你說我怎么就攤上這事腊状。” “怎么了苔可?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵缴挖,是天一觀的道長。 經(jīng)常有香客問我焚辅,道長映屋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任同蜻,我火速辦了婚禮秧荆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘埃仪。我一直安慰自己乙濒,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布卵蛉。 她就那樣靜靜地躺著颁股,像睡著了一般。 火紅的嫁衣襯著肌膚如雪傻丝。 梳的紋絲不亂的頭發(fā)上甘有,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音葡缰,去河邊找鬼亏掀。 笑死忱反,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的滤愕。 我是一名探鬼主播温算,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼间影!你這毒婦竟也來了注竿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤魂贬,失蹤者是張志新(化名)和其女友劉穎巩割,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體付燥,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡宣谈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了键科。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒲祈。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖萝嘁,靈堂內(nèi)的尸體忽然破棺而出梆掸,到底是詐尸還是另有隱情,我是刑警寧澤牙言,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布酸钦,位于F島的核電站,受9級特大地震影響咱枉,放射性物質(zhì)發(fā)生泄漏卑硫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一蚕断、第九天 我趴在偏房一處隱蔽的房頂上張望欢伏。 院中可真熱鬧,春花似錦亿乳、人聲如沸硝拧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽障陶。三九已至,卻和暖如春聊训,著一層夾襖步出監(jiān)牢的瞬間抱究,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工带斑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鼓寺,地道東北人勋拟。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像妈候,于是被迫代替她去往敵國和親敢靡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容