【OpenHarmony/HarmonyOs 】元素周期表页面开发:18 列网格、自适应布局与分类筛选

【OpenHarmony/HarmonyOs 】元素周期表页面开发:18 列网格、自适应布局与分类筛选 【OpenHarmony/HarmonyOs 】元素周期表页面开发18 列网格、自适应布局与分类筛选元素周期表是「化学视界」中最核心的页面之一。它不仅要展示 118 个元素还要支持搜索、分类筛选、图例说明、详情跳转和不同屏幕适配。本文记录我是如何开发这个页面的。⚛️一、周期表页面的开发难点元素周期表看起来只是一个表格但真正开发时会遇到不少问题元素分布不是普通列表而是固定行列。主表有 18 列小屏幕展示压力很大。不同元素类别需要不同颜色。用户需要搜索元素名称、符号、序号。点击元素后要能查看详细信息。平板和手机要有不同显示密度。所以我没有用普通List实现周期表而是为元素位置、分类、弹窗和详情跳转分别做了设计。二、元素数据中保存行列位置元素模型里包含row和colexport interface ChemicalElement {number:number; symbol:string;name:string; atomicMass:string; category: ElementCategory; row:number; col:number; }这样页面不需要自己推算元素在哪一行哪一列直接根据数据定位。我开发时的经验是周期表这种结构化内容位置信息应该放在数据层而不是写死在 UI 层。否则后期维护会非常痛苦。三、18 列网格的基础设计周期表主表使用 18 列const PERIODIC_GRID_COLUMNS: string 1fr .repeat(18).trimEnd();这个写法很简洁表示 18 个等宽列。周期表的每个元素格子再根据row和col放到对应位置。对于化学学习来说保留周期表原始结构非常重要。用户看到的不应该只是元素列表而应该是熟悉的周期表布局。四、分类颜色让元素类型一眼可识别不同元素类别有不同背景色getCategoryBgResource(category: ElementCategory): Resource { const colorMap: RecordElementCategory, Resource { alkali_metal:$r(app.color.element_alkali_metal), alkaline_earth:$r(app.color.element_alkaline_earth), transition_metal:$r(app.color.element_transition_metal), nonmetal:$r(app.color.element_nonmetal), halogen:$r(app.color.element_halogen), noble_gas:$r(app.color.element_noble_gas)}; return colorMap[category]||$r(app.color.element_unknown); }分类颜色让页面更像真正的学习工具。用户不需要点开每个元素也能通过颜色大致判断元素类型。五、深色模式下单独处理颜色周期表页面还根据深浅色模式调整文字颜色privateisDarkTheme(): boolean {returnthis.sysColorMode ConfigurationConstant.ColorMode.COLOR_MODE_DARK; }深色模式下如果直接使用浅色模式的颜色有些元素格子会显得刺眼有些文字对比度不够。所以我为深色环境单独准备了颜色映射。这是开发 UI 时很容易忽略的一点深色模式不是简单反色而是重新建立颜色层级。六、搜索模式和分类模式分开周期表页面中有两个主要浏览方式搜索元素。按分类筛选。状态设计如下StatesearchText: string ;StateselectedCategory: ElementCategory |allall;StateisSearchMode: boolean false;StatesearchResults: ChemicalElement[] [];当用户输入内容时进入搜索模式清空搜索后回到分类浏览。这样用户不会同时被搜索结果和分类筛选干扰。七、分类筛选的判断逻辑分类匹配逻辑很简单isCategoryMatch(element: ChemicalElement): boolean {returnthis.selectedCategory all|| element.category this.selectedCategory; }我没有把它写在渲染表达式里而是单独封装成函数。这样代码更容易读后续如果要增加多条件筛选也有地方扩展。八、点击反馈元素格子也要有触感周期表是高密度页面如果点击没有反馈用户很难判断自己是否点中了元素。因此我给元素格子加了缩放状态getElementCellScale(number:number):number{returnthis.elementCellScales[number] ||1; }setElementCellScale(number:number, scale:number) {this.elementCellScales[number] scale; }每个元素用原子序数作为 key维护自己的缩放状态。这比用一个全局 scale 更合理因为用户点击哪个元素就只有哪个元素反馈。九、元素详情预览与详情页跳转周期表页支持元素预览弹窗也支持进入详情页。我的设计是点击元素先展示关键内容。用户想深入了解时再进入详情页。这样做比每次点击都直接跳转更轻量。用户在周期表里浏览时可以快速查看多个元素不会频繁切页面。元素详情页则展示更完整的信息原子序数。元素符号。中文名和英文名。原子量。电子排布。密度、熔点、沸点。发现年份和发现者。元素简介。十、平板适配让周期表更像工具周期表最怕小屏拥挤所以我根据屏幕宽度判断是否为大屏constdisplayClass: display.Display display.getDefaultDisplaySync();constdensity displayClass.densityDPI;constscreenWidthVp density 0? displayClass.width / density *160:360;this.isTabletMode screenWidthVp 600;this.elementCellHeight this.isTabletMode ?52:40;大屏上元素格子更高标题和文字也更舒展小屏上则保持紧凑保证信息尽量完整展示。十一、图例弹窗降低颜色理解成本周期表用了大量颜色区分元素类别但并不是所有用户都能马上理解颜色含义。所以我还设计了图例入口。图例数据本身也是结构化的StatelegendItems: LegendItem[] [ { name:碱金属, cat:alkali_metal}, { name:碱土金属, cat:alkaline_earth}, { name:过渡金属, cat:transition_metal}, { name:非金属, cat:nonmetal}, { name:卤素, cat:halogen}, { name:稀有气体, cat:noble_gas} ];我开发这个弹窗时的想法是颜色可以帮助记忆但必须提供解释。尤其是学习类 App不能让用户靠猜。图例入口放在页面头部右侧不占用主表空间。用户需要时点开不需要时不会干扰浏览。十二、搜索结果为什么单独展示周期表本身是结构化网格但搜索结果更适合用列表展示。比如用户搜索“铁”时他更关心匹配结果而不是铁在周期表中具体空格周围的布局。所以搜索模式和主表模式是分开的主表模式保持周期表结构。搜索模式突出匹配结果。这也是我开发周期表页面时的一个取舍同一个数据源可以根据用户意图切换不同展示方式。十三、我开发周期表页面的总结这个页面最重要的不是“画出 118 个格子”而是把结构、分类、搜索、适配和详情连接起来。我的实现思路是⚛️ 数据层保存元素位置。 分类颜色辅助理解。 搜索和分类模式分离。 每个元素都有独立点击反馈。 手机紧凑展示平板增强可读性。 预览弹窗和详情页分工明确。元素周期表是化学学习 App 的门面功能。把它做好整个应用的专业感会明显提升。