Action Status MIT License

SwiftTheming 🎨 是一个方便轻量级的主题管理器,它基于系统范围的外观(浅色和深色外观)处理多个主题,并覆盖应用程序的系统外观。

📱 演示

this slowpoke moves

您可以在 Example 文件夹中查看演示项目。

🎉 动机

想象一下,您想要注入多个主题,并根据当前的系统外观或您喜欢的外观来管理它们。由于 SwiftUI 没有提供管理不同主题的机制,因此您必须自己想办法。对我来说,我想专注于其他耗时的事情,而不是把时间花在这上面。因此,为开发者实现方便机制的想法油然而生,我最终开始制作它。这就是 SwiftTheming 的由来。🎉🎉🎉 使用 SwiftTheming,我们可以随心所欲地管理主题和系统外观,而无需付出太多努力。您所要做的就是声明具有不同颜色、图像、字体和渐变的主题。非常容易!

⚠️要求

SwiftTheming 是使用 Xcode 13.0 开发的。请确保您正在使用 Xcode 13 及更高版本。

🛠 安装

📦 使用 Swift Package Manager

将其作为依赖项添加到您的 Package.swift 中。

dependencies: [
    .package(url: "https://github.com/dscyrescotti/SwiftTheming.git", from: "2.0.0")
]

📦 使用 Cocoapods

将其添加到您的 Podfile 中。

pod 'SwiftTheming', '~> 2.0.0'

目前,SwiftTheming 只能通过 Swift Package Manager 和 Cocoapods 安装。

👀 版本 2 的迁移指南

SwiftTheming 🎨 已发布版本 2,其中包括代码架构和开发者体验的重大改进。请查看迁移指南 以从版本 1 迁移。

🎯 用法

声明多个主题

要开始使用,您需要定义四种不同类型的资源,分别用于颜色、字体、渐变和图像。稍后,在创建不同主题时,将通过将它们作为类型别名注入来使用它们。

enum ColorAsset: ColorAssetable {
    case backgroundColor
    // more...
}
enum FontAsset: FontAssetable { /* more... */ }
enum GradientAsset: GradientAssetable { /* more... */ }
enum ImageAsset: ImageAssetable { /* more...}

您可以省略某些资源,除非您打算在主题中使用它们。

现在,我们可以开始使用声明的资源来指定不同的主题。

class SampleTheme: Themed, Assetable {
    typealias _ColorAsset = ColorAsset
    typealias _FontAsset = FontAsset
    typealias _GradientAsset = GradientAsset
    typealias _ImageAsset = ImageAsset

    func colorSet(for asset: ColorAsset) -> ColorSet {
        switch asset {
        case .backgroundColor:
            return ColorSet(light: Color(hex: 0xDEF8EA), dark: Color(hex: 0x22442E))
        }
    }
    func imageSet(for asset: ImageAsset) -> ImageSet { /* some stuff*/ }
    func fontSet(for asset: FontAsset) -> FontSet { /* some stuff */ }
    func gradientSet(for asset: GradientAsset) -> GradientSet { /* some stuff */ }
}

对于空资源,您可以直接使用 EmptyAsset 而不是声明资源。

class SampleTheme: Themed, Assetable {
  typealias _GradientAsset = EmptyAsset
}

在创建多个主题之后,就可以在 Theme 扩展中列出您将在应用程序中使用的所有主题,并为 Themeable 协议提供所需的规范。

extension Theme: Themeable {
    static let sampleTheme = Theme(key: "sampleTheme")
    // more themes
    
    public func themed() -> Themed {
        switch self{
        case .sampleTheme: return SampleTheme()
        // some stuff
        default: fatalError("You are accessing undefined theme.")
        }
    }
}

声明默认主题

在进入解释如何在视图层中使用主题提供程序和访问界面元素的部分之前,您需要首次运行设置默认主题和外观。 您可以通过让 DefaultTheming 符合 Defaultable 并提供所需的将用作默认值的主题和外观来实现它。

extension DefaultTheming: Defaultable {
    public func defaultTheme() -> Theme {
        .sampleTheme
    }
    
    public func defaultAppearance() -> PreferredAppearance {
        .system
    }
}

跨视图访问主题提供程序

太棒了! 您已准备好在视图中使用主题。 让我们开始传递 ThemeProvider 实例,该实例作为环境对象存在于视图层次结构中,以便可以在各个视图中访问它。

WindowGroup {
    ContentView()
        .themeProviding()
}

现在,您可以通过 @ThemeProviding 属性包装器在任何视图内部访问 ThemeProvider,以便您可以通过 themeProvider 完全管理主题并覆盖系统外观。

struct ContentView: View {
    @ThemeProviding var themeProvider
    
    var body: some View { /* some stuff */ }
}

您可以通过分别调用 setTheme(with:)setPreferredAppearance(with:) 来切换主题和外观。

🔎 探索

要了解有关 SwiftTheming 🎨 的更多信息,您可以查看文档或深入研究源代码。

✍️ 作者

Scotti (@dscyrescotti)

👨‍💻 贡献

如果您有任何增强功能的想法,或者遇到任何错误,SwiftTheming 🎨 欢迎所有开发者做出贡献并提出问题。

© 许可证

SwiftTheming 🎨 在 MIT 许可证下可用。 有关更多信息,请参见LICENSE文件。