Harmony os 技术实战|拼豆制图49:五组分类视觉规则如何收口成一张配置表

拼豆图库包含动漫、游戏、偶像、场景和设计师五组内容。每组都有主色、浅背景、图片蒙层、卡片底色、角标、符号和副标题。如果每个视觉字段都写一组 if (category === ...),页面很快会出现七八条平行判断链。

本文把这些规则收口成类型化配置,让组件只消费视觉结果,不再负责解释分类;同时保留默认项,保证旧数据或未知分类不会让页面失去样式。

一、平行判断链会悄悄产生视觉漂移

categoryTint()categorySoftBg()categoryMark()categorySubtitle() 分散存在时,新增分类必须修改多处函数。漏改任何一处都不会报错,却可能出现"背景是新分类、角标还是默认值"的混搭。

这类问题的本质是同一个业务实体被拆成多条无关联分支。正确方向不是继续封装更多函数,而是把一个分类的完整视觉规则放在同一个对象中。

二、把分类键收窄为有限集合

先阻止任意字符串进入视觉系统:

ts 复制代码
export type CategoryKey =
  'anime' | 'game' | 'idol' | 'scene' | 'designer' | 'default'

export interface CategoryVisualConfig {
  tint: ResourceColor
  softBg: ResourceColor
  imageVeil: ResourceColor
  cardTint: ResourceColor
  accent: ResourceColor
  mark: string
  corner: string
  subtitle: string
}

字段清单就是视觉契约。评审新增分类时,可以直接确认颜色、文案和装饰是否齐全。

三、同一分类的规则必须相邻

把五组配置放入一个映射,下面展示其中三组及默认项:

ts 复制代码
export const CATEGORY_VISUALS: Record<CategoryKey, CategoryVisualConfig> = {
  anime: {
    tint: '#FFE2F0', softBg: '#FFF0F7', imageVeil: '#35FFF0F8',
    cardTint: '#FFF1F5', accent: ThemeTokens.brandPink,
    mark: '漫', corner: '✦', subtitle: '魔法少女与学院角色'
  },
  game: {
    tint: '#DDEEFF', softBg: '#EEF6FF', imageVeil: '#35EAF6FF',
    cardTint: '#EEF8FF', accent: ThemeTokens.sky,
    mark: '游', corner: '◇', subtitle: '勇者、法师与像素冒险'
  },
  scene: {
    tint: '#DFF5DD', softBg: '#ECF9EA', imageVeil: '#35ECFFE9',
    cardTint: '#F0FAEA', accent: ThemeTokens.mintDark,
    mark: '景', corner: '☾', subtitle: '樱花街角与梦幻小屋'
  },
  idol: {
    tint: '#FFF0B8', softBg: '#FFF8DF', imageVeil: '#35FFF2D9',
    cardTint: '#FFF7E5', accent: '#D78E00',
    mark: '星', corner: '♡', subtitle: '舞台应援 Q 版爱豆'
  },
  designer: {
    tint: '#F1DDFF', softBg: '#F8EEFF', imageVeil: '#35F6EAFF',
    cardTint: '#F4EDFF', accent: '#A368D8',
    mark: '潮', corner: '✧', subtitle: '潮玩盲盒原创娃娃'
  },
  default: {
    tint: '#F4F0F3', softBg: '#F8F5F7', imageVeil: '#35FFFFFF',
    cardTint: '#FFFCFD', accent: ThemeTokens.ink,
    mark: '图', corner: '☆', subtitle: '精选编号图纸'
  }
}

每组配置独立成块,修改场景色时不会误碰游戏副标题。

四、在单一入口处理未知分类

数据层中的 Pattern.category 可能仍是 string,尤其需要兼容旧记录时。不要在每个组件强制断言,统一通过解析函数进入有限集合:

ts 复制代码
export function toCategoryKey(value: string): CategoryKey {
  if (value === 'anime' || value === 'game' || value === 'idol' ||
    value === 'scene' || value === 'designer') {
    return value
  }
  return 'default'
}

export function visualOf(category: string): CategoryVisualConfig {
  return CATEGORY_VISUALS[toCategoryKey(category)]
}

默认项是兼容边界,不是让错误分类长期沉默的理由。数据校验仍应记录未知值,界面则使用安全样式继续展示。

五、组件一次读取,连续消费

组件不再重复调用七个分类函数,只读取一个配置对象:

ts 复制代码
@Builder
private CategoryCard(item: CategoryItem) {
  Column() {
    Text(visualOf(item.key).corner)
      .fontColor(visualOf(item.key).accent)
    Text(visualOf(item.key).mark)
      .fontColor(visualOf(item.key).accent)
    Text(visualOf(item.key).subtitle)
      .fontColor(ThemeTokens.inkSoft)
  }
  .backgroundColor(visualOf(item.key).cardTint)
}

更进一步,可以在数据准备阶段把视觉配置附加到视图数据,避免一次构建中重复解析:

ts 复制代码
export interface CategoryViewData {
  item: CategoryItem
  visual: CategoryVisualConfig
}

六、业务数据和视觉数据不要互相复制

Pattern 只保存 category,不应把 tintcorner 等字段重复写入每张图纸。否则调整主题后要迁移所有旧记录。

推荐关系是:

text 复制代码
Pattern.category
      ↓
toCategoryKey()
      ↓
CATEGORY_VISUALS
      ↓
CategoryCard / PatternCard / Cover

分类键是稳定业务数据,具体颜色和文案是可演进的展示规则,两者通过读取关系连接。

七、主题色优先引用 ThemeTokens

配置表并不意味着重新堆积十六进制颜色。品牌色、正文色、背景色等跨页面语义仍应引用 ThemeTokens;只有分类专属色保留在分类配置中。

ts 复制代码
designer: {
  tint: '#F1DDFF',
  softBg: '#F8EEFF',
  imageVeil: '#35F6EAFF',
  cardTint: '#F4EDFF',
  accent: '#A368D8',
  mark: '潮',
  corner: '✧',
  subtitle: '潮玩盲盒原创娃娃'
}

若分类色未来也需要深浅模式,可把 accent 替换为资源引用,配置结构不需要变化。

八、透明色要明确通道顺序

图片蒙层使用八位颜色,例如 #35FFF0F8。在当前 ArkUI 写法里应明确团队约定的通道顺序,并用一张小色块页面验证透明度,避免有人按另一种顺序改成完全不同的颜色。

可以把蒙层透明度统一为同一档位,只改变 RGB 部分。这样五组卡片保持相近的图片可读性,不会有某一组蒙层过重遮住封面。

验证时选择同一张明暗对比明显的封面,分别套用五组蒙层,在浅色与深色系统外观下观察标题、角标和主体轮廓。若某组需要特殊透明度,也应把差异写进配置,而不是在组件里临时叠加第二层颜色。

九、配置完整性可以自动断言

配置表适合做关系校验:文字不可为空、角标应是短字符、默认项必须存在。

ts 复制代码
export function validateCategoryVisuals(): string[] {
  const issues: string[] = []
  const keys: CategoryKey[] = [
    'anime', 'game', 'idol', 'scene', 'designer', 'default'
  ]

  keys.forEach((key: CategoryKey) => {
    const visual = CATEGORY_VISUALS[key]
    if (visual.mark.length === 0) {
      issues.push(`${key} 缺少分类符号`)
    }
    if (visual.subtitle.trim().length === 0) {
      issues.push(`${key} 缺少副标题`)
    }
    if (visual.corner.length > 2) {
      issues.push(`${key} 的角标过长`)
    }
  })
  return issues
}

这类断言无法判断颜色好不好看,却能防止新增分类时漏掉必要字段。

十、一次改造不要同时重做视觉

从判断链迁移到配置表时,应先保持现有颜色和文案完全不变。建议按以下顺序实施:

  1. 录入当前所有返回值;
  2. 给旧函数与新配置输入同一分类,比较结果;
  3. 组件改读 visualOf()
  4. 删除已经没有引用的旧函数;
  5. 最后再单独调整某个分类视觉。

结构改造和视觉改版分开,出现差异时更容易判断来源。

十一、落地检查清单

  • 分类键是有限类型;
  • 一个分类的全部视觉字段放在同一对象;
  • 未知分类统一回退到 default
  • 组件不再编写分类判断链;
  • Pattern 不重复保存视觉字段;
  • 跨页面语义色继续使用 ThemeTokens
  • 五组现有视觉在迁移前后保持一致。

迁移验收可以截取五组分类卡片、图纸卡片和分类封面各一屏,与改造前逐项比较。只有配置读取路径发生变化,颜色、符号、副标题和回退行为都不应改变,这样后续视觉调整才有干净的基线。

总结

配置表的价值不只是减少代码行数,而是让"一组分类视觉"重新成为一个完整对象。五组规则集中后,新增字段、调整主题和排查样式差异都有唯一入口;ArkUI 组件只负责展示,不再承担分类解释逻辑。对于分类丰富的 Harmony os 图库,这种单一映射能显著降低视觉漂移。

标签:Harmony os、ArkTS、ArkUI、配置化、主题设计

相关推荐
2501_919749032 小时前
华为鸿蒙免费决策APP—小羊挠头
华为·harmonyos·鸿蒙
m0_749690232 小时前
【寻迹校园 HarmonyOS NEXT 实战 37】一套 ArkUI 适配四档宽度:sm、md、lg、xl 响应式 Shell 实战
华为·harmonyos·arkui·navigation·响应式布局·多设备适配
RisunJan4 小时前
HarmonyOS 架构精读:从系统分层到应用模型
华为·架构·harmonyos
见山是山-见水是水4 小时前
从需求到页面:鸿蒙原生 Ability 与 ArkTS 交互的 ArkTS 原生实现
华为·harmonyos
见山是山-见水是水4 小时前
网络请求性能优化落地指南:让原生界面在模拟器里稳定运行
网络协议·华为·性能优化·harmonyos
2501_919749034 小时前
华为鸿蒙免费语音记录APP—小羊回响
华为·harmonyos·鸿蒙
less_121384 小时前
HarmonyOS WPS Open SDK:旧 HAR 迁移到统一接口联调指南
华为·sdk·harmonyos·wps·鸿蒙开发·文档编辑
yuhulkjv3354 小时前
告别复制粘贴式降级:纳米AI鸿蒙版导出word格式为何绕不开“AI 导出鸭”
人工智能·ai·word·harmonyos·ai导出鸭
HwJack205 小时前
鸿蒙 Accessibility Kit 全景解析:无障碍开发从哪里下手
microsoft·华为·harmonyos