iOS 项目中的多主题颜色设计与实现
引言
在现代iOS应用中,用户对个性化体验的需求越来越高,除了功能上的满足,多样的视觉风格也是提升用户体验的重要手段之一。提供多主题颜色的切换功能不仅能满足用户的审美偏好,还可以让应用更具活力,适应不同场景下的使用需求。列好的主题切换设计能提升应用的整体品质。
在这篇博客中,我将分享一个简单而灵活的多主题颜色管理方案,我们将通过使用工厂模式和协议的组合,实现不同主题颜色的管理与切换功能。无论是为应用提供个性化的主题颜色,还是为了后续的主题扩展,这种设计都能为项目带来更好的可维护性和扩展性。
主题颜色切换架构概述
为了实现多主题颜色管理,我们采用了工厂模式与协议模式的组合。通过定义个通用的颜色协议(ZMColorFactory),我们可以为不同的主题提供一致的接口,同时保证代码的灵活性和可扩展性。每个主题的颜色实现由独立的工厂类负责,根据用户选择或应用内的设置来动态切换主题。这种设计不仅能有效地管理不同的主题颜色,还可以轻松扩展未来的新主题。
项目额整体架构可以分为以下几部分:
颜色工厂协议
颜色工厂协议定义了不同主题颜色所需的接口,例如主题颜色,文字颜色等。所有的颜色工厂都应该遵循该协议,确保各个主体能够提供一致的颜色属性。
颜色工厂
每个主题的颜色工厂类实现了颜色工厂的协议,提供具体的颜色值。例如,红色主题工厂提供红色的主题颜色,而蓝色的主题工厂则提供蓝色的主题和文字颜色。
主题管理器
主题管理器是整个架构的核心,负责根据用户选择或系统设置来切换主题。通过主题管理器,我们可以动态地从不同的颜色工厂中获取当前主题的颜色。
主题切换功能
主题管理器能够根据用户偏好或者其它逻辑比如启动时的默认主题,在不同的颜色工厂之间切换。当主题切换时,应用的颜色会即时更新,提升用户体验。
主题颜色切换文件介绍
主题枚举
在我们实现多主题管理的过程中,首先需要定义一个枚举来表示不同的主题类型。在ZMTheme文件中,我们定义了一个ZMTheme枚举,用于列举所有可用的主题。为了简化示例代码,我们只定义了两个主题:红色和蓝色。当然实际项目中可以根据需求添加更多主题。
enum ZMTheme {/// 红色主题case red/// 蓝色主题case blue
}
这个枚举将用于在应用中表示用户所选择的主题,并通过主题管理器根据该枚举值来切换不同的主题工厂,从而实现主题颜色的动态更新。
颜色工厂协议
为了确保每个主题能够提供一致的颜色方案,我们定义了一个颜色工厂协议ZMColorFactory。这个协议为每个主题提供了统一的接口,规定了所有主题都必须包含的颜色属性。通过这种方式,不同主题可以根据各自的风格实现自己的颜色,但依然遵循同样的接口,从而保证在应用中不同主题的颜色切换能够无缝衔接。
ZMColorFactory协议的定义如下:
protocol ZMColorFactory {/// 主题的主色调var themeColor: UIColor { get }/// 标题文字颜色var titleColor: UIColor { get }....
}
同样为了简洁我们在协议中定义了两个基本的颜色属性:
- themeColor:每个主题的主色调,通常用于页面的导航栏,按钮颜色等等。
- titleColor:用于显示大标题文字的颜色。
通过这个协议,我们可以确保每个主题工厂都能提供这些颜色属性。这样,在后续的主题工厂实现中,不同的主题只需要实现这个协议即可提供自己的特定的颜色方案,而主题管理器则可以通过这个统一接口轻松地访问这些颜色。
颜色工厂
在定义了ZMColorFactory协议之后,我们通过不同的工厂类来实现各个主题的具体颜色方案。每个工厂类复杂提供一套完整的颜色配置,这样可以确保在应用中不同主题的颜色实现能够根据用户的选择动态切换。同样为了简洁,我们定义两个颜色工厂ZMBaseColorFactory和ZMBlueColorFactory。
基础主题工厂
ZMBaseColorFactory是我们项目中的基本主题工厂,它实现了ZMColorFactory协议,并默认的红色主题提供颜色配置:
class ZMBaseColorFactory: NSObject, ZMColorFactory {/// 主题色var themeColor: UIColor {return UIColor.zm_hex("#FB233B")}/// 标题文字颜色var titleColor: UIColor {return UIColor.zm_hex("#333333")}
}
在这个工厂中,我们通过返回固定的颜色值实现了红色主题的主色调和标题文字颜色。主色调是红色(#FB233B),标题文字使用深灰色(#333333)
蓝色主题工厂
ZMBlueColorFactory是另一个实现了ZMColorFactory协议的工厂类,为蓝色主题提供颜色方案:
class ZMBlueColorFactory: NSObject, ZMColorFactory {/// 主题色var themeColor: UIColor {return UIColor.blue}/// 标题文字颜色var titleColor: UIColor {return UIColor.blue}
}
在这个工厂中,我们为蓝色主题提供了主色调和标题文字颜色,简洁起见二者都是用了系统的UIColor.blue。
扩展性
通过这种工厂类的设计,每当我们需要新增一个主题时,只需实现ZMColorFactory协议,并在新的工厂类中定义该主题的颜色属性。这样不仅代码结构清晰,还能保证新旧主题的无缝切换。
主题颜色管理器
为了实现高效的主题管理,我们还需要引入ZMColorHelper类作为主题管理器。该管理器负责整个应用的主题初始化、更新和颜色获取,确保用户的主题选择能够即时反映在应用界面中。
class ZMColorHelper: NSObject {/// 当前颜色工厂static private var colorFactory: ZMColorFactory = ZMBaseColorFactory()/// 启动主题管理器static func startUp() {// 从用户默认设置中读取当前主题if let theme = UserDefaults.standard.object(forKey: "theme") as? ZMTheme {updateTheme(theme: theme)}}/// 更新主题/// - Parameter theme: 主题/// - Returns: Voidstatic func updateTheme(theme: ZMTheme) {switch theme {case .red:colorFactory = ZMBaseColorFactory()case .blue:colorFactory = ZMBlueColorFactory()}// 将当前主题存储到用户默认设置中UserDefaults.standard.set(theme, forKey: "theme")}/// 获取当前主题色static var themeColor: UIColor {return colorFactory.themeColor}/// 标题文字颜色static var titleColor: UIColor {return colorFactory.titleColor}}
启动主题管理器
在startUp()方法中,管理器会从用户的默认设置中读取存储的主题值。如果用户之前选择过主题,管理器会响应地更新当前主题。
更新主题
通过updateTheme(theme:)方法,管理器可以根据传入的主题枚举值来选择不同的颜色工厂。当用户更改主题时,需要对用这个方法。从而更新colorFactory为相应的主题工厂。同时,当前选择的主题也会被存储到用户的默认设置中,以便下次启动应用时能够恢复到上次使用的主题。
获取主题颜色
themeColor和titleColor静态属性返回当前需要获取的颜色,任何需要使用主题颜色的地方都可以通过这些属性来获取。这样,整个应用的颜色管理变得更加集中和简洁。
ZMColorHepler类作为主题管理器,为多主题功能提供了清晰的接口和逻辑,使得主题额管理、更新和颜色获取变得简便而高效。通过集中管理,我们可以确保应用的外观在不同主题间切换时能够无缝衔接,提升用户体验。
颜色扩展
为了简化颜色创建的和管理,我们使用UIColor类扩展了两个使用的方法:zm_rgba和zm_hex。这使得在项目中使用颜色变得更加方便和直观。
extension UIColor {/// RGBA颜色/// - Parameters:/// - r: red/// - g: green/// - b: blue/// - a: alpha/// - Returns: 生成的颜色class func zm_rgba(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ a: CGFloat = 1.0) -> UIColor {return UIColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: a)}/// 通过16进制字符串生成颜色/// - Parameters:/// - hex: 16进制字符串/// - alpha: 透明度/// - Returns: 生成的颜色class func zm_hex(_ hex: String, _ alpha: CGFloat = 1.0) -> UIColor {var cString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()if cString.hasPrefix("#") {cString.removeFirst()}if cString.count != 6 {return UIColor.clear}let rString = String(cString.prefix(2))let gString = String(cString[cString.index(cString.startIndex, offsetBy: 2)..<cString.index(cString.startIndex, offsetBy: 4)])let bString = String(cString.suffix(2))var r: UInt64 = 0, g: UInt64 = 0, b: UInt64 = 0Scanner(string: rString).scanHexInt64(&r)Scanner(string: gString).scanHexInt64(&g)Scanner(string: bString).scanHexInt64(&b)return UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: alpha)}
}
使用zm_rgba
zm_rgba允许开发者使用红、绿、蓝和透明度值轻松创建颜色。
let customColor = UIColor.zm_rgba(255, 50, 50, 1.0) // 创建一个不透明的红色
使用zm_hex
zm_hex方法使得通过16进制字符快速创建颜色成为可能,特别对于设计师提供的颜色值。
let hexColor = UIColor.zm_hex("#FB233B") // 创建对应的颜色
使用主题颜色切换功
在实际项目中,使用ZMColorHelper进行主题管理就非常简单。一下是一些基本的使用步骤。
启动主题管理
在应用启动时,首选需要调用startUp()方法来初始化主题管理器。这个方法会检测用户的默认设置并加载之前选择的主题。
// 在应用启动时调用
ZMColorHelper.startUp()
切换主题
要切换主题,只需要调用updateTheme(theme:)方法并传入所需的主题枚举值。管理器会根据传入的主题更新相应的颜色工厂,并保持选择的主题到用户默认设置中。
// 切换到红色主题
ZMColorHelper.updateTheme(theme: .red)// 切换到蓝色主题
ZMColorHelper.updateTheme(theme: .blue)
获取当前主题颜色
在需要使用当前主题颜色的地方,可以通过themeColor属性轻松获取主题的颜色。无论实在设置背景色、文字颜色都可以直接使用。
// 设置视图的背景颜色为当前主题色
view.backgroundColor = ZMColorHelper.themeColor// 设置标题的文字颜色为当前主题的标题色
label.textColor = ZMColorHelper.titleColor
结语
在本文中,我们探讨了如何在iOS项目中实现多主题颜色管理。通过引入ZMColorHelper主题管理器和相关的颜色工厂协议,我们构建了一个灵活且易于扩展的主题系统。无论是通过简单的枚举定义主题,还是通过工厂模式实现颜色的具体化,我们的设计都旨在提供清晰的接口和无缝的用户体验。
随着用户对应用个性化需求的不断增加,支持多主题功能不仅提升了用户体验,还增强了应用的吸引力。希望通过本篇文章,能够帮助开发者更好地理解和实现多主题管理的最佳实现,使我们的应用在视觉效果上更具吸引力。
相关文章:

iOS 项目中的多主题颜色设计与实现
引言 在现代iOS应用中,用户对个性化体验的需求越来越高,除了功能上的满足,多样的视觉风格也是提升用户体验的重要手段之一。提供多主题颜色的切换功能不仅能满足用户的审美偏好,还可以让应用更具活力,适应不同场景下的…...

Android Camera2 与 Camera API技术探究和RAW数据采集
Android Camera2 Android Camera2 是 Android 系统中用于相机操作的一套高级应用程序接口(API),它取代了之前的 Camera API。以下是关于 Android Camera2 的一些主要信息: 主要特点: 强大的控制能力:提供…...
[python][pipenv]pipenv的使用
pipenv 是一个 Python 开发工作流程的工具,它旨在将 pip 的包管理和 virtualenv 的虚拟环境管理结合起来。以下是一些基本的 pipenv 使用方法: 安装 pipenv: 如果你还没有安装 pipenv,可以通过 pip 安装它: pip insta…...

SpringSession微服务
一.在linux中确保启动起来redis和nacos 依赖记得别放<dependencyManagement></dependencyManagement>这个标签去了 1.首先查看已经启动的服务 docker ps 查看有没有安装redis和nacos 2.启动redis和nacos 发现没有启动redis和nacos,我们先来启动它。,…...
强化学习:通过试错学习最优策略---示例:使用Q-Learning解决迷宫问题
强化学习(Reinforcement Learning, RL)是一种让智能体(agent)在与环境交互的过程中,通过最大化某种累积奖励来学习如何采取行动的学习方法。它适用于那些需要连续决策的问题,比如游戏、自动驾驶和机器人控制…...

OpenGL ES 纹理(7)
OpenGL ES 纹理(7) 简述 通过前面几章的学习,我们已经可以绘制渲染我们想要的逻辑图形了,但是如果我们想要渲染一张本地图片,这就需要纹理了。 纹理其实是一个可以用于采样的数据集,比较典型的就是图片了,我们知道我…...

【C#】CacheManager:高效的 .NET 缓存管理库
在现代应用开发中,缓存是提升性能和降低数据库负载的重要技术手段。无论是 Web 应用、桌面应用还是移动应用,缓存都能够帮助减少重复的数据查询和处理,从而提高系统的响应速度。然而,管理缓存并不简单,尤其是当你需要处…...

【数学分析笔记】第4章第2节 导数的意义和性质(2)
4. 微分 4.2 导数的意义与性质 4.2.3 单侧导数 f ′ ( x ) lim Δ x → 0 f ( x Δ x ) − f ( x ) Δ x lim x → x 0 f ( x ) − f ( x 0 ) x − x 0 f(x)\lim\limits_{\Delta x\to 0}\frac{f(x\Delta x)-f(x)}{\Delta x}\lim\limits_{x\to x_0}\frac{f(x)-f(x_0)…...

深度学习:迁移学习
目录 一、迁移学习 1.什么是迁移学习 2.迁移学习的步骤 1、选择预训练的模型和适当的层 2、冻结预训练模型的参数 3、在新数据集上训练新增加的层 4、微调预训练模型的层 5、评估和测试 二、迁移学习实例 1.导入模型 2.冻结模型参数 3.修改参数 4.创建类ÿ…...

Footprint Growthly Quest 工具:赋能 Telegram 社区实现 Web3 飞速增长
作者:Stella L (stellafootprint.network) 在 Web3 的快节奏世界里,社区互动是关键。而众多 Web3 社区之所以能够蓬勃发展,很大程度上得益于 Telegram 平台。正因如此,Footprint Analytics 精心打造了 Growthly —— 一款专为 Tel…...
进入xwindows后挂起键盘鼠标没有响应@FreeBSD
问题: 在升级pkg包后,系统无法进入xfce等xwindows,表现为黑屏和看见鼠标,左上角有一个白字符块,键盘鼠标没有反应,整个系统卡住。但是可以ssh登录,内部的服务一切正常。 表现 处理过程…...
CentOS7.9 snmptrapd更改162端口
端口更改前: 命令: netstat -an |grep 162 [root@kibana snmp]# netstat -an | grep 162 udp 0 0 0.0.0.0:162 0.0.0.0:* unix 3 [ ] STREAM CONNECTED 45162 /run/systemd/journal/stdout u…...

模糊测试SFuzz亮相第32届中国国际信息通信展览会
9月25日,被誉为“中国ICT市场的创新基地和风向标”的第32届中国国际信息通信展在北京盛大开幕,本次展会将在为期三天的时间内,为信息通信领域创新成果、尖端技术和产品提供国家级交流平台。开源网安携模糊测试产品及相关解决方案精彩亮相&…...
CMake学习
向大佬lyf学习,先把其8服务器中所授fine 文章目录 前言一、CMakeList.txt 命令1. 最外层CMakeLists1.1 cmake_minimum_required()1.2 project()1.3 set()1.4 add_subdirectory(&…...

书生·浦语大模型全链路开源开放体系
书生浦语大模型全链路开源开放体系 大模型应用生态的发展和繁荣是建立在模型基座强大的通用基础能力之上的。上海AI实验室联合团队研究认为,大模型各项性能提升的基础在于语言建模能力的增强,对于大模型的研究应回归语言建模本质,通过更高质量…...
PHP安装swoole扩展无效,如何将文件上传至Docker容器
目录 过程 操作方式 过程 在没有使用过云服务器以前,Docker这个平台一直都很神秘。在我申请了华为云服务器,并使用WordPress镜像去搭建自己的网站以后,我不得不去把Docker平台弄清楚,原因是我使用的一个主题需要安装swoole扩展,才能够正常启用。而要将swoole.so这个扩展…...
Web3.0 应用项目
Web3.0 是下一代互联网的概念,旨在去中心化、用户拥有数据控制权和通过区块链技术实现信任的网络。Web3.0的应用项目主要集中在区块链、加密货币、去中心化应用 (DApps)、去中心化金融 (DeFi)、NFT(非同质化代币)等领域。以下是一些典型的 We…...
Linux 学习笔记(十六)—— 重定向与缓冲区
一、文件重定向 矩阵的下标,也就是文件描述符的分配规则,是从0开始空的最小的文件描述符分配给进程新打开的文件;文件输出重定向的原理是,关掉1(输出),然后打开文件,这个新打开的文…...

828华为云征文|WordPress部署
目录 前言 一、环境准备 二、远程连接 三、WordPress简介 四、WordPress安装 1. 基础环境安装 编辑 2. WordPress下载与解压 3. 创建站点 4. 数据库配置 总结 前言 WordPress 是一个非常流行的开源内容管理系统(Content Management System, CMS…...

华为开源自研AI框架昇思MindSpore应用案例:计算高效的卷积模型ShuffleNet
如果你对MindSpore感兴趣,可以关注昇思MindSpore社区 ShuffleNet ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型,和MobileNet, SqueezeNet等一样主要应用在移动端,所以模型的设计目标就是利用有限的计算资源来达到…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...