繁体   English   中英

为 iOS 应用添加深色模式

[英]Adding dark mode to iOS app

我正在尝试向我的应用程序添加一个主题(一个黑暗的主题)。 因此,当用户单击活动开关时,它会使整个应用程序进入黑暗模式。 我对黑暗模式进行了硬编码,只是为了看看它会是什么样子; 但是现在我希望能够通过 UISwitch 启用和禁用它,但我不知道该怎么做?

class DarkModeTableViewCell: UITableViewCell {

var DarkisOn = Bool()
let userDefaults = UserDefaults.standard


@IBOutlet var darkModeSwitchOutlet: UISwitch!

override func awakeFromNib() {
    super.awakeFromNib()


}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}


@IBAction func darkModeSwitched(_ sender: Any) {

    if darkModeSwitchOutlet.isOn == true {

        //enable dark mode

        DarkisOn = true

        userDefaults.set(true, forKey: "DarkDefault")
        userDefaults.set(false, forKey: "LightDefault")



    } else {

        //enable light mode
        DarkisOn = false

        userDefaults.set(false, forKey: "DarkDefault")
        userDefaults.set(true, forKey: "LightDefault")
    }

}



}



class DarkModeViewController: UIViewController {



func set(for viewController: UIViewController) {



    viewController.view.backgroundColor = UIColor(red: 0.1, green: 0.1, blue: 0.1, alpha: 1.0)
        viewController.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    viewController.navigationController?.navigationBar.tintColor =     UIColor.white
    viewController.navigationController?.navigationBar.barStyle =     UIBarStyle.black
    viewController.tabBarController?.tabBar.barStyle = UIBarStyle.black






}
static let instance = DarkModeViewController()
}

然后我要做的是在每个视图控制器中调用该函数以查看它的外观,但是如果开关打开或关闭,我需要能够访问 bool 值,如果是,则让它执行该功能,否则只是保持不变。 如果您有任何其他问题,请告诉我,我知道其中一些可能没有多大意义。

更新:这个问题(因此,这个答案)是在 iOS 13 发布之前编写的,因此它不使用 iOS 13 特定的 API。


我会使用 Notifications ( NSNotificationCenter APIs ) 解决这个问题。

这个想法是在启用暗模式和禁用暗模式时实时通知您的视图控制器,因此它们也可以实时适应变化。 您不需要检查开关的状态或类似的东西。

首先创建两个通知(您也可以只使用一个通知并在userInfo字典中传递所需的主题,但在这种情况下,创建两个通知更容易,因为您需要使用 Swift 进行转换和其他什么)。

NotificationsName+Extensions.swift

import Foundation

extension Notification.Name {
    static let darkModeEnabled = Notification.Name("com.yourApp.notifications.darkModeEnabled")
    static let darkModeDisabled = Notification.Name("com.yourApp.notifications.darkModeDisabled")
}

在所有“主题化”视图控制器上,收听这些通知:

    override func viewDidLoad() {
        super.viewDidLoad()

        // Add Observers
        NotificationCenter.default.addObserver(self, selector: #selector(darkModeEnabled(_:)), name: .darkModeEnabled, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(darkModeDisabled(_:)), name: .darkModeDisabled, object: nil)
    }

不要忘记在deinit删除它们,因为向无效对象发送通知会引发异常:

deinit {
    NotificationCenter.default.removeObserver(self, name: .darkModeEnabled, object: nil)
    NotificationCenter.default.removeObserver(self, name: .darkModeDisabled, object: nil)
}

在您的“主题化”视图控制器中,实现darkModeEnabled(_:)darkModeDisabled(_:)

@objc private func darkModeEnabled(_ notification: Notification) {
    // Write your dark mode code here
}

@objc private func darkModeDisabled(_ notification: Notification) {
    // Write your non-dark mode code here
}

最后,切换您的开关将触发任一通知:

@IBAction func darkModeSwitched(_ sender: Any) {

    if darkModeSwitchOutlet.isOn == true {
        userDefaults.set(true, forKey: "darkModeEnabled")

        // Post the notification to let all current view controllers that the app has changed to dark mode, and they should theme themselves to reflect this change.
        NotificationCenter.default.post(name: .darkModeEnabled, object: nil)

    } else {

        userDefaults.set(false, forKey: "darkModeEnabled")

        // Post the notification to let all current view controllers that the app has changed to non-dark mode, and they should theme themselves to reflect this change.
        NotificationCenter.default.post(name: .darkModeDisabled, object: nil)
    }

}

这样,当“主题”发生变化时,您的所有视图控制器都会实时收到通知,并且它们会做出相应的反应。 请注意,您需要采取措施在应用程序启动时显示正确的模式,但我确定您正在这样做,因为您正在使用 UserDefaults 并且可能正在检查它们。 还值得一提的是 NSNotificationCenter 不是线程安全的,尽管这无关紧要,因为无论如何这些 UI 代码都应该进入主线程。

有关更多信息,您可以查看NSNotificationCenter 文档

注意:此代码建立在 OP 的基础上。 它可以简化(例如,您不需要同时跟踪“亮”和“暗”状态,只需跟踪一个)。

从 iOS 13 苹果推出了深色主题,如果你想在你的 iOS 应用中添加深色主题,你可以在 viewDidLoad() 上应用以下代码行,如:

        if #available(iOS 13.0, *) {
            overrideUserInterfaceStyle = .dark
        } else {
            // Fallback on earlier versions
        }

因此,您可以更改主题,例如有 2 个选项浅色或深色主题。 但是,如果您正在编写上述代码,则只有在运行 iOS 13 的设备上才会始终采用深色主题。

overrideUserInterfaceStyle = .light

或者,如果您的设备已经在 iOS 13 上运行,您可以更改主题,例如:

在此处输入图片说明

您甚至可以检查当前设置的主题,例如:

if self.traitCollection.userInterfaceStyle == .dark{
    print("Dark theme")
 }else{
    print("Light theme")
}

让我们看看这个例子:

override func viewDidLoad() {
       super.viewDidLoad()

       if self.traitCollection.userInterfaceStyle == .dark{
           self.view.backgroundColor = UIColor.black
       }else{
            self.view.backgroundColor = UIColor.white
  }

}

结果:

在此处输入图片说明

在此处输入图片说明

这是相同的视频: https : //youtu.be/_k6YHMFCpas

基本上有两种方法可以为您的应用程序设置主题。 方法一:使用苹果的UIAppearance代理。 如果您的应用程序在所有视图和控件中的颜色使用非常一致,那么这非常有效,如果您有一堆异常,则效果不佳。 在这种情况下,我建议使用像SwiftTheme这样的第三方 pod

请注意,这种方法已被 Apple 在全球范围内将“暗模式”引入(几乎)所有平台所取代。 现在要走的路是具有外观变体的“命名颜色”。

要在 iOS 13 及更高版本中支持暗模式,您可以使用 unicolor Closure。

    @objc open class DynamicColor : NSObject{
        public   var light :  UIColor
        public   var dark :  UIColor
        public  init(light : UIColor,dark : UIColor) {
            self.light = light
            self.dark = dark
        }
    }
    extension DynamicColor{
      public  func resolve() -> UIColor{
           return UIColor.DynamicResolved(color: self)

        }
    }
    extension UIColor{
       class func DynamicResolved(color: DynamicColor) -> UIColor{
        if #available(iOS 13.0, *) {
            let dynamicColor = UIColor { (traitCollection: UITraitCollection) -> UIColor in
                if traitCollection.userInterfaceStyle == .dark {
                    return color.dark
                } else {
                    return color.light
                }
            }
            return dynamicColor
        } else {
            // Fallback on earlier versions
            return color.light
        }
        }

    }

在视图中使用它时

UIView().backgroundColor =  DynamicColor(light: .white, dark: .black).resolve()
//OR
UIView().backgroundColor =  UIColor.DynamicColor(light: .white, dark: .black)

在 SwiftUI 中,这变得更容易了。 只需在视图中包含环境变量colorScheme并检查它的暗模式,如下所示:

struct DarkModeView: View {
    @Environment(\.colorScheme) var colorScheme: ColorScheme

    var body: some View {
        Text("Hi")
            .foregroundColor(colorScheme == .dark ? .white : .black)
    }
}

有一个关于这一切是如何工作的一个伟大的文章在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM