HarmonyOS ArkTS 工具网格与路由导航:从小工具百宝箱看卡片式布局与页面跳转的实战技巧

发布时间:2026/7/20 19:24:41

HarmonyOS ArkTS 工具网格与路由导航:从小工具百宝箱看卡片式布局与页面跳转的实战技巧 引子一个应用塞五个小工具工具箱应用——把二维码生成、单位换算、随机决策、颜色提取、倒计时五个小工具集成到一个应用里。需求很简单首页放五个卡片点击跳转到对应工具页面。看起来就是画五个卡片加个跳转但做起来发现几个细节要处理卡片的阴影和圆角怎么配合、网格布局怎么自适应、路由跳转怎么传参、渐变背景怎么和卡片颜色协调。这个应用虽然功能不复杂但涉及了 ArkUI 开发的多个实用知识点。今天就从 Index.ets 的代码出发聊聊工具网格的设计和路由导航的实现。完整效果项目结构多页面的应用架构和星空运势应用不同这个工具箱是多页面架构——每个工具一个独立页面entry/src/main/ets/ ├── pages/ │ ├── Index.ets # 首页工具网格 │ ├── QRGenerator.ets # 二维码生成 │ ├── UnitConverter.ets # 单位换算 │ ├── RandomTool.ets # 随机决策 │ ├── ColorPicker.ets # 颜色提取 │ └── Countdown.ets # 倒计时 ├── entryability/ │ └── EntryAbility.ets └── resources/为什么用多页面而不是 Swiper星空运势应用用 Swiper 在三个页面间切换因为三个功能是并列的用户可能频繁切换。但工具箱的五个工具是独立的——用户通常只用一个工具不需要在工具间切换。用路由跳转router.pushUrl更合适每个工具独立运行不共享状态跳转到工具页面后用户可以返回首页再选另一个工具页面栈管理更清晰push 进去pop 回来router 的引入import{router}fromkit.ArkUI;router是 ArkUI 的页面路由模块提供页面跳转、返回、传参等功能。kit.ArkUI是鸿蒙系统的 UI 框架包包含所有 UI 相关的 API。ToolItem 接口工具数据的建模interfaceToolItem{name:string;// 工具名称desc:string;// 工具描述icon:string;// emoji 图标page:string;// 跳转页面路径color:string;// 卡片背景色}为什么用 interface 而不是 class工具数据是只读的不需要实例化方法用interface比class更轻量。interface编译后不会生成额外的 JavaScript 代码包体积更小。字段的设计考量name显示在卡片上的标题简短有力desc显示在卡片上的描述说明工具用途iconemoji 图标比图片加载快兼容性好page路由路径点击卡片时跳转到对应页面color卡片背景色每个工具有自己的主题色为什么 color 不用枚举颜色值用字符串而不是枚举是因为灵活性可以直接用 CSS 颜色值不需要额外定义枚举简洁性#4F6EF7比Color.BLUE更直观扩展性如果以后要加更多颜色不需要修改枚举定义工具数据五个工具的定义tools:ToolItem[][{name:二维码生成,desc:输入文字或链接即时生成二维码,icon:,page:pages/QRGenerator,color:#4F6EF7},{name:单位换算,desc:长度·重量·温度·面积·数据,icon:,page:pages/UnitConverter,color:#34C759},{name:随机决策,desc:抛硬币·掷骰子·随机数·抽签,icon:,page:pages/RandomTool,color:#FF6B35},{name:颜色提取,desc:从图片取色智能配色方案,icon:,page:pages/ColorPicker,color:#AF52DE},{name:倒计时,desc:设定事件日实时倒数动画,icon:⏳,page:pages/Countdown,color:#FF2D55},];数据和 UI 的分离工具数据定义在组件内部tools数组但和 UI 渲染逻辑分离。如果要加新工具只需要在数组里加一个对象不需要改 UI 代码。颜色的选择五个工具用了五种不同的颜色工具颜色色系二维码生成#4F6EF7蓝色单位换算#34C759绿色随机决策#FF6B35橙色颜色提取#AF52DE紫色倒计时#FF2D55红色五种颜色饱和度相近在深色背景上都能看清但又各有区分。用户可以通过颜色快速识别工具——“蓝色是二维码绿色是换算”。page 路径的格式pages/QRGenerator是路由路径格式是pages/页面名。不需要加.ets后缀路由会自动查找对应的组件。路由跳转navTo 方法navTo(page:string):void{router.pushUrl({url:page});}router.pushUrl 的用法router.pushUrl把目标页面压入页面栈用户可以返回上一页。参数是一个对象url是目标页面的路径。为什么封装成 navTo直接调用router.pushUrl({ url: item.page })也可以但封装成navTo有两个好处语义化this.navTo(item.page)比router.pushUrl({ url: item.page })更易读可扩展如果以后要加路由拦截比如登录检查只需要改navTo方法不需要改所有 onClick页面栈的管理pushUrl会把目标页面压入栈顶用户按返回键会 pop 回首页。这是鸿蒙系统的标准导航模式不需要额外处理。如果要替换当前页面不保留首页在栈中可以用router.replaceUrl。但工具箱需要保留首页所以用pushUrl。页面布局头部 网格build(){Column(){// 头部Column(){Text( 小工具百宝箱).fontSize(26).fontWeight(FontWeight.Bold).fontColor(#FFFFFF)Text(精选实用小工具一个应用全搞定).fontSize(13).fontColor(#888888).margin({top:6})}.width(100%).padding({left:20,right:20,top:60,bottom:24}).alignItems(HorizontalAlign.Start)// 工具卡片网格Scroll(){Grid(){...}}.layoutWeight(1).scrollBar(BarState.Off)}.width(100%).height(100%).linearGradient({direction:GradientDirection.Bottom,colors:[[#1A1A2E,0.0],[#16213E,0.5],[#0F3460,1.0]]})}头部区域头部用 Column 居左对齐alignItems(HorizontalAlign.Start)包含标题和副标题标题26px 粗体白色醒目副标题13px 灰色说明用途paddingtop 60px 留出状态栏空间bottom 24px 和网格隔开网格区域网格用ScrollGrid实现Scroll让网格可以滚动工具数量多时layoutWeight(1)占据剩余空间scrollBar(BarState.Off)隐藏滚动条渐变背景.linearGradient({direction:GradientDirection.Bottom,colors:[[#1A1A2E,0.0],[#16213E,0.5],[#0F3460,1.0]]})背景是从深蓝到更深蓝的渐变顶部#1A1A2E最浅的深蓝色中间#16213E中等深度底部#0F3460最深的蓝色这种渐变让页面有深度感比纯色背景更高级。Grid 布局2 列自适应Grid(){ForEach(this.tools,(item:ToolItem,idx:number){GridItem(){Column(){Text(item.icon).fontSize(42).margin({bottom:14})Text(item.name).fontSize(17).fontWeight(FontWeight.Bold).fontColor(#FFFFFF).margin({bottom:6})Text(item.desc).fontSize(11).fontColor(#AAFFFFFF).maxLines(2).textAlign(TextAlign.Center)}.width(100%).height(160).borderRadius(18).backgroundColor(item.color).justifyContent(FlexAlign.Center).shadow({radius:8,color:item.color44,offsetY:4}).onClick(()this.navTo(item.page))}})}.columnsTemplate(1fr 1fr).columnsGap(14).rowsGap(14).padding({left:20,right:20,top:8,bottom:80}).width(100%)columnsTemplate 的用法.columnsTemplate(1fr 1fr)定义了两列等宽布局。1fr表示占剩余空间的比例两个1fr就是两列各占一半。如果要三列改成1fr 1fr 1fr。如果要不等宽可以用2fr 1fr第一列是第二列的两倍宽。间距的控制columnsGap(14)列间距 14pxrowsGap(14)行间距 14pxpadding({left:20,right:20,top:8,bottom:80})左右留 20px 边距底部留 80px避免被系统导航栏遮挡卡片的尺寸每个卡片width(100%).height(160)宽度自适应列宽高度固定 160px。固定高度保证所有卡片高度一致视觉上整齐。卡片样式圆角、阴影、背景色圆角.borderRadius(18)给卡片 18px 的圆角。大圆角让卡片看起来更柔和符合现代 UI 设计趋势。阴影.shadow({radius:8,color:item.color44,offsetY:4})阴影有三个参数radius: 8阴影模糊半径越大越模糊color: item.color44阴影颜色用卡片颜色加 4426% 透明度offsetY: 4阴影垂直偏移让阴影在卡片下方为什么阴影颜色用卡片颜色用灰色阴影#00000044也可以但用卡片颜色的半透明版本更有发光感——蓝色卡片的阴影是蓝色的绿色卡片的阴影是绿色的。背景色.backgroundColor(item.color)用工具数据中的颜色作为卡片背景。每个工具有自己的主题色用户可以通过颜色快速识别。内容居中.justifyContent(FlexAlign.Center)让卡片内容垂直居中。图标、名称、描述三个元素在卡片中间排列不会偏上或偏下。卡片内容图标、名称、描述Column(){Text(item.icon).fontSize(42).margin({bottom:14})Text(item.name).fontSize(17).fontWeight(FontWeight.Bold).fontColor(#FFFFFF).margin({bottom:6})Text(item.desc).fontSize(11).fontColor(#AAFFFFFF).maxLines(2).textAlign(TextAlign.Center)}三个元素的层次元素字体大小颜色作用图标42px默认视觉焦点名称17px 粗体白色工具名称描述11px半透明白色工具用途图标最大吸引注意力名称粗体告诉用户这是什么描述最小补充说明。描述的截断.maxLines(2)限制描述最多显示两行超过两行显示省略号。这样可以保证卡片高度一致不会因为描述太长导致卡片参差不齐。文字颜色标题纯白色#FFFFFF最醒目描述半透明白色#AAFFFFFF比标题弱化但比背景突出踩坑记录坑 1Grid 的高度计算Grid 的高度是自动计算的但如果子组件高度不一致可能导致布局错乱。代码中给每个 GridItem 设了固定高度160避免了这个问题。坑 2Scroll 的 scrollBar默认情况下 Scroll 会显示滚动条影响美观。.scrollBar(BarState.Off)隐藏滚动条。坑 3router 的路径格式路由路径不需要加.ets后缀。写pages/QRGenerator而不是pages/QRGenerator.ets。坑 4底部 padding网格底部留了 80px 的 padding是为了避免被系统导航栏遮挡。如果底部工具卡片被导航栏挡住可以增大这个值。坑 5渐变背景的方向GradientDirection.Bottom表示从上到下渐变。如果要从下到上用GradientDirection.Top。代码改进建议1. 工具数据外部化当前工具数据写在组件内部。如果以后要加更多工具建议移到独立文件// data/Tools.tsexportconstTOOLS:ToolItem[][...];2. 卡片点击动画当前卡片点击没有反馈。可以加缩放动画.scale({x:this.scaleVal,y:this.scaleVal}).animation({duration:150}).onClick((){this.scaleVal0.95;setTimeout((){this.scaleVal1;},150);this.navTo(item.page);})3. 路由传参如果要给工具页面传参比如从首页传入初始值可以用router.pushUrl的paramsrouter.pushUrl({url:page,params:{initialValue:xxx}});然后在目标页面用router.getParams()获取。4. 页面栈管理如果用户从工具页面返回首页后想清空页面栈避免多次返回可以用router.clear()。5. 搜索功能如果工具数量增多可以加搜索功能。用TextInput组件接收搜索关键词过滤tools数组。总结小工具百宝箱的首页核心是数据驱动网格——把工具数据用 Grid 渲染成卡片点击通过 router 跳转到对应页面。卡片的圆角、阴影、背景色配合渐变背景视觉效果干净整洁。适用边界这个部分适合用作 ArkUI 工具网格和路由导航的学习案例涵盖了 ToolItem 接口设计、Grid 布局、router.pushUrl、卡片样式、渐变背景等核心知识点。但如果要上架应用商店还需要补充搜索功能、工具分类、最近使用、收藏功能、路由传参等内容。建议在此基础上逐步扩展而不是一次性做完所有功能。

相关新闻