惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
S
Security Affairs
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
Microsoft Security Blog
Microsoft Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
美团技术团队
月光博客
月光博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
有赞技术团队
有赞技术团队
博客园 - 叶小钗
Hugging Face - Blog
Hugging Face - Blog
Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
Vercel News
Vercel News
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
C
Cisco Blogs
T
Tor Project blog
The Hacker News
The Hacker News
雷峰网
雷峰网
MyScale Blog
MyScale Blog
博客园 - 司徒正美
AWS News Blog
AWS News Blog
GbyAI
GbyAI
Y
Y Combinator Blog
D
DataBreaches.Net
Simon Willison's Weblog
Simon Willison's Weblog
S
Securelist
The GitHub Blog
The GitHub Blog
S
SegmentFault 最新的问题
T
Tenable Blog
L
LangChain Blog
M
MIT News - Artificial intelligence
N
Netflix TechBlog - Medium
The Cloudflare Blog
A
About on SuperTechFans
IT之家
IT之家
F
Fortinet All Blogs
Security Latest
Security Latest
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
NISL@THU
NISL@THU
爱范儿
爱范儿
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
W
WeLiveSecurity
A
Arctic Wolf
I
Intezer
Application and Cybersecurity Blog
Application and Cybersecurity Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
现代化 UI 架构:三层颜色体系与系统化设计方案
goodlords · 2026-05-19 · via DEV Community

本文是 UI 架构系列 的第一篇,将深入探讨颜色层的设计。后续文章将依次介绍:

:本文以 Android 为例进行说明,但核心思想完全适用于 iOS、React、H5、小程序等任何平台。


前言

在多年的跨平台 App 开发实践中,我发现 UI 资源管理是困扰许多团队的共性问题:

  • 颜色定义混乱,同一个色值重复定义几十次
  • 组件形态与颜色过度耦合,难以复用
  • 样式属性重复书写,维护成本极高
  • 主题切换困难,夜间模式适配工作量巨大
  • 新同事需要花费大量时间理解混乱的颜色命名

如果你也被这些问题困扰,这个系列或许值得一读——主要面向设计总监、设计师、研发总监与前端工程师。

本文要点

  1. 三层颜色架构的设计理念和核心原则
  2. 每一层的具体设计规范和代码实现
  3. 如何实现日间/夜间模式的无缝切换
  4. 架构的适用场景和扩展方向

架构全景

本系列介绍的是一套完整的 UI 架构体系,其中三层颜色架构是核心基础:

箭头表示引用/依赖方向:应用层引用 func_;func_* 引用 t_;t_ 引用基础色。定义权在设计侧,自下而上配置。*

颜色层依赖关系func_*t_* → 基础色(严格单向依赖)

本文聚焦于三层颜色架构的完整设计,后续文章将介绍上层应用层如何基于颜色层构建。


一、传统颜色管理的核心痛点

1.1 真实项目中的反例

在我接触过的多个项目中,经常会看到类似这样的颜色定义:

<!-- 从真实项目中截取的颜色定义 -->
<color name="bg_login">#FFFFFF</color>      <!-- 登录页背景 -->
<color name="bg_home">#F5F5F5</color>      <!-- 首页背景 -->
<color name="bg_profile">#FFFFFF</color>    <!-- 个人中心背景 -->
<color name="text_title">#141414</color>   <!-- 标题文字 -->
<color name="text_desc">#808080</color>    <!-- 描述文字 -->
<color name="text_hint">#BFBFBF</color>    <!-- 提示文字 -->
<color name="button_red">#DB121F</color>   <!-- 红色按钮 -->
<color name="red_button">#DB121F</color>   <!-- 另一个红色按钮 -->

Enter fullscreen mode Exit fullscreen mode

1.2 问题分析

问题类型 具体表现 影响
重复定义 #FFFFFF#DB121F 多次出现 改一处需改所有地方,容易遗漏
业务绑定 bg_loginbg_home 与具体页面绑定 无法复用,扩展性差
命名混乱 button_redred_button 同时存在 新人难以选择,团队协作困难
夜间模式灾难 需复制所有颜色到 values-night 工作量巨大,容易出错

1.3 根本原因

这些问题的本质在于:颜色定义与业务语义、主题逻辑过度耦合。当一个颜色既承载了"背景"的业务含义,又承载了"白色"的具体色值时,任何改动都会牵一发而动全身。


二、三层颜色架构设计理念

针对这些问题,我设计了一套严格单向依赖的三层颜色架构:

2.1 架构核心原则

层级 唯一职责 命名规则 是否承载业务语义 修改频率
基础色层 定义原始色值 色系_数字(如 white_1 ❌ 否 极低(品牌升级时才改)
主题层 日间/夜间模式映射 t_色系_数字(如 t_white_1 ❌ 否 低(新增主题时才改)
功能色层 UI 职能封装(文本、背景、边框等) func_{色系}_{职能}_{档位}(如 func_black_text_1 ❌ 否 由设计师维护(新增档位/职能时改)

重要说明:功能色层封装的是 UI 职能(如文本、背景、边框),而非具体业务场景。func_black_text_1 代表黑色系主档文本色,可用于商品标题、页面标题、按钮文字等任何场景,不绑定具体业务。功能色的定义权归属设计师,研发只引用、不新增。

2.2 严格单向依赖规则

为什么必须严格遵守单向依赖?

  • 避免循环依赖导致的颜色定义混乱
  • 每层只做自己的事,职责清晰,便于定位问题
  • 改一处全局生效,维护成本极低
  • 多人开发不会互相冲突

三、分层详解:每一层该怎么设计

3.1 第一层:全局基础色层

定位:纯原始色值定义,不做任何主题绑定和业务关联

命名规则色系_数字 下划线格式,数字按明度/饱和度递增

设计原则

  • 白色系:数字越小越浅(white_1 = 纯白)
  • 黑色系:数字越小越浅(black_1 = 浅灰)
  • 彩色系:数字越小饱和度越低
  • 不参与日夜切换,保持绝对稳定

完整基础色表(与仓库实现一致):

色系 档位数 命名区间 / 说明
白色系 4 white_1 ~ white_4
黑色系 8 black_1 ~ black_8
灰色系 7 gray_1 ~ gray_7
红色系 4 red_1 ~ red_4
橙色系 4 orange_1 ~ orange_4;含 orange_0orange_2borange_3b
黄色系 4 yellow_1 ~ yellow_4
蓝色系 4 blue_1 ~ blue_4
绿色系 4 green_1 ~ green_4
补间色 按需 black_5a
透明度变体 按需 基础色名_alpha{透明度}

代码示例

<!-- ✅ 正确:统一色系_数字命名 -->
<color name="white_1">#FFFFFF</color>
<color name="black_8">#000000</color>
<color name="red_4">#DB121F</color>
<color name="black_1">#F0F0F0</color>
<color name="white_1_alpha20">#33FFFFFF</color>

Enter fullscreen mode Exit fullscreen mode

3.2 第二层:主题适配层(t_)

定位:唯一的日夜模式映射层,只做色值代理,不承载任何业务语义

命名规则t_基础色名,与基础色一一对应

设计原则

  • 只引用基础色层变量,绝对不写具体色值
  • 日间/夜间模式通过 Android 资源限定符自动切换
  • 保持与基础色完全一致的命名,便于维护

错误做法(常见误区)

<!-- ❌ 错误:主题层承载了业务语义 -->
<!-- values/colors.xml -->
<color name="t_bg_page">#FFFFFF</color>
<color name="t_text_main">#000000</color>

<!-- values-night/colors.xml -->
<color name="t_bg_page">#141414</color>
<color name="t_text_main">#FFFFFF</color>

Enter fullscreen mode Exit fullscreen mode

问题:主题层承载了业务语义,破坏了分层原则。新增主题时需要复制所有业务语义的颜色。

正确做法

<!-- ✅ 正确:只做颜色映射,不关心用途 -->
<!-- values/colors_theme_tokens.xml(日间模式) -->
<color name="t_white_1">@color/white_1</color>
<color name="t_black_8">@color/black_8</color>
<color name="t_orange_4">@color/orange_4</color>

<!-- values-night/colors_theme_tokens.xml(夜间模式) -->
<color name="t_white_1">@color/black_8</color>   <!-- 背景色反转 -->
<color name="t_black_8">@color/white_1</color>   <!-- 主文字色反转 -->
<color name="t_orange_4">@color/orange_3b</color> <!-- 夜间使用较浅的橙色 -->

Enter fullscreen mode Exit fullscreen mode

优势

  • 主题层只做颜色映射,不关心用途
  • 新增主题只需要加一个资源目录
  • 夜间模式切换完全由 Android 系统自动处理,零代码侵入

3.3 第三层:功能色层(func_)

定位:面向 UI 职能的语义抽象层,不承载业务语义(如「登录页背景」「删除按钮红」)

命名规则func_{色系}_{职能}_{档位},档位数字按该职能下的深浅/重要性递增

设计原则

  • 只引用主题层变量,绝对不直接引用基础色
  • 采用「色系 × 职能 × 数字档位」模式,保留无限扩展能力
  • 由设计师在资源文件中定义与维护;研发在布局/代码中只引用已有 token

为什么我反对固定语义命名?

很多人喜欢这样定义功能色:

<color name="func_text_main">@color/t_black_8</color>
<color name="func_text_sub">@color/t_black_5</color>
<color name="func_text_aux">@color/t_black_3</color>

Enter fullscreen mode Exit fullscreen mode

这在实际项目中会出问题:中间态越来越多,命名很快失控。比如需要一个介于 subaux 之间的颜色时,该叫 func_text_sub2 还是 func_text_medium

最佳实践:色系 + 职能 + 数字档位

<!-- 黑色系文本:档位越小越深、越重要 -->
<color name="func_black_text_1">@color/t_black_8</color>
<color name="func_black_text_2">@color/t_black_7</color>
<color name="func_black_text_3">@color/t_black_5</color>
<color name="func_black_text_4">@color/t_black_3</color>

<!-- 黑色系背景:档位越小越浅 -->
<color name="func_black_bg_1">@color/t_black_8</color>
<color name="func_black_bg_2">@color/t_black_7</color>

<!-- 橙色系强调 -->
<color name="func_orange_text_1">@color/t_orange_4</color>
<color name="func_orange_bg_1">@color/t_orange_4</color>

Enter fullscreen mode Exit fullscreen mode

无限扩展能力

  • 需要在 func_black_text_2func_black_text_3 之间加一档,由设计师新增 func_black_text_25 即可
  • 不用造 func_product_title 这类业务名
  • 规范可长期稳定

职能分类速览(详见第六节完整矩阵):

职能后缀 命名示例 典型用途
_text func_black_text_1 各级文字
_bg func_gray_bg_1 页面、卡片背景
_border func_gray_border_1 边框
_divider func_black_divider_1 分割线
_alpha func_black_alpha_1 遮罩、半透明
_shadow func_black_shadow_1 阴影

四、两个关键争议点的深度解析

4.1 争议1:主题层到底该不该承载业务语义?

我的答案:绝对不应该

主题层的本质是颜色代理,它的唯一职责是根据当前主题返回对应的基础色。它不应该关心这个颜色是用来做背景还是文字。

如果主题层承载了业务语义:

  • 每新增一个主题,你都要复制所有业务语义的颜色
  • 业务语义变化时,你需要修改所有主题文件
  • 架构的解耦性被完全破坏

4.2 争议2:功能层用数字命名会不会可读性差?

不会,只要约定好规则

我们只需要在团队内部约定:

  • 文本色:数字越小越重要、越深
  • 背景色:数字越小越浅
  • 边框色:数字越小越深

新人只需要花 5 分钟就能记住这些规则,比记住几十个不同的语义名称要容易得多。


五、核心优势:为什么这套架构能解决问题?

5.1 维护成本显著降低

改色流程对比

操作 传统做法 三层架构
改品牌色 全局搜索替换几百个地方 修改基础色层一处
适配夜间模式 修改所有颜色定义 自动切换,零代码
新增页面 定义 5-10 个新颜色 复用设计师已定义的功能色

5.2 无限扩展能力

  • 新增色系:只需要在基础色层添加
  • 新增主题:只需要加一个资源目录
  • 新增 UI 职能档位:由设计师在功能层顺延数字编号

5.3 团队协作零成本

  • 统一的命名规范,没有歧义
  • 新成员 5 分钟就能上手
  • 多人开发不会互相冲突

六、功能色层详解:7大色系 × 6种职能

在实际项目中,我们发现一个 App 中常用的颜色职能只需要6种

职能 用途 示例
文本色 文字显示 标题、正文、辅助文字
背景色 填充区域 页面背景、卡片背景
边框色 勾勒边界 输入框边框、卡片边框
分割线 分隔内容 列表分割线、区域分隔
透明度 半透明效果 遮罩、玻璃效果
阴影色 阴影效果 卡片阴影、按钮阴影

而这 6 种职能,组合7大色系,就构成了一个完整的颜色体系。

6.1 为什么是这7大色系?

色系 特点 主要用途
黑色系 从纯黑到浅灰的完整灰阶 正文、次要文字、背景
灰色系 独立的灰色梯度 辅助信息、禁用状态
红色系 高饱和度警示色 错误、删除、警告
黄色系 温和警示色 待处理、进行中
橙色系 强调色 热销、促销、主按钮
蓝色系 信任色 链接、信息、成功
绿色系 正向色 成功、增长、完成

6.2 完整颜色矩阵

文本色(7色系 × 4档 = 28个)

色系 命名 深浅/饱和度
黑色系 func_black_text_1 ~ func_black_text_4 1最深 → 4最浅
灰色系 func_gray_text_1 ~ func_gray_text_4 1最深 → 4最浅
红色系 func_red_text_1 ~ func_red_text_4 1高饱和 → 4低饱和
黄色系 func_yellow_text_1 ~ func_yellow_text_4 1高饱和 → 4低饱和
橙色系 func_orange_text_1 ~ func_orange_text_4 1高饱和 → 4低饱和
蓝色系 func_blue_text_1 ~ func_blue_text_4 1高饱和 → 4低饱和
绿色系 func_green_text_1 ~ func_green_text_4 1高饱和 → 4低饱和

背景色(7色系 × 2档 = 14个)

色系 命名 用途
黑色系 func_black_bg_1, func_black_bg_2 深色背景
灰色系 func_gray_bg_1, func_gray_bg_2 浅灰背景、卡片
红色系 func_red_bg_1, func_red_bg_2 错误背景
黄色系 func_yellow_bg_1, func_yellow_bg_2 警告背景
橙色系 func_orange_bg_1, func_orange_bg_2 强调背景
蓝色系 func_blue_bg_1, func_blue_bg_2 信息背景
绿色系 func_green_bg_1, func_green_bg_2 成功背景

边框色(7色系 × 2档 = 14个)

色系 命名 用途
黑色系 func_black_border_1, func_black_border_2 常规边框
灰色系 func_gray_border_1, func_gray_border_2 辅助边框
红色系 func_red_border_1, func_red_border_2 错误边框
黄色系 func_yellow_border_1, func_yellow_border_2 警告边框
橙色系 func_orange_border_1, func_orange_border_2 强调边框
蓝色系 func_blue_border_1, func_blue_border_2 信息边框
绿色系 func_green_border_1, func_green_border_2 成功边框

分割线、透明度、阴影色(各7色系 × 2档 = 各14个):

色系 分割线命名 透明度命名 阴影命名
黑色系 func_black_divider_1~2 func_black_alpha_1~2 func_black_shadow_1~2
灰色系 func_gray_divider_1~2 func_gray_alpha_1~2 func_gray_shadow_1~2
红色系 func_red_divider_1~2 func_red_alpha_1~2 func_red_shadow_1~2
黄色系 func_yellow_divider_1~2 func_yellow_alpha_1~2 func_yellow_shadow_1~2
橙色系 func_orange_divider_1~2 func_orange_alpha_1~2 func_orange_shadow_1~2
蓝色系 func_blue_divider_1~2 func_blue_alpha_1~2 func_blue_shadow_1~2
绿色系 func_green_divider_1~2 func_green_alpha_1~2 func_green_shadow_1~2

理论矩阵规模:7 色系 × 6 职能 × 2–4 档 ≈ 84 个 token,可覆盖绝大多数通用 UI 场景。本仓库 demo 仅实现常用子集(见 colors_semantic.xml);完整矩阵由设计师按产品需要逐步补齐,研发不自行「补色」。

6.3 核心原则:职能无关,业务通用

这套颜色体系是业务无关的。同一个 func_red_text_1

  • 在电商 App 中可以用作「商品下架」提示
  • 在社交 App 中可以用作「被拉黑」提示
  • 在金融 App 中可以用作「交易失败」提示

颜色本身不承载业务语义,业务语义由使用场景决定。

6.4 反例 vs 正例

反例:业务绑定

<!-- ❌ 错误:业务绑定,无法复用 -->
<color name="func_product_delete_text">@color/t_red_5</color>    <!-- 商品删除文字 -->
<color name="func_order_cancel_text">@color/t_red_5</color>    <!-- 订单取消文字 -->

Enter fullscreen mode Exit fullscreen mode

正例:职能无关

<!-- ✅ 正确:职能无关,业务通用 -->
<color name="func_red_text_1">@color/t_red_5</color>    <!-- 任何需要红色文字的地方 -->
<color name="func_red_text_2">@color/t_red_4</color>    <!-- 任何需要浅红文字的地方 -->

Enter fullscreen mode Exit fullscreen mode

6.5 完整命名规范速查表

命名公式func_{色系}_{职能}_{档位}

色系前缀

前缀 色系 示例
black 黑色系 func_black_text_1
gray 灰色系 func_gray_text_1
red 红色系 func_red_text_1
yellow 黄色系 func_yellow_text_1
orange 橙色系 func_orange_text_1
blue 蓝色系 func_blue_text_1
green 绿色系 func_green_text_1

职能后缀

后缀 职能 档位
_text 文本色 1-4档
_bg 背景色 1-2档
_border 边框色 1-2档
_divider 分割线 1-2档
_alpha 透明度 1-2档
_shadow 阴影色 1-2档

七、总结

这套三层颜色架构的核心思想其实很简单:解耦

  • 把色值定义和主题适配解耦
  • 把主题适配和 UI 职能语义解耦(职能语义仍由设计师定义,不绑定具体业务页面)
  • 每一层只做自己最擅长的事

通过「7大色系 × 6种职能」的设计,我们构建了一套完整、可扩展、业务无关的颜色体系,覆盖 App 所有通用 UI 场景。


参考代码

💡 如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、转发。关注我,获取更多 Android 架构设计干货。