写点什么

卡片导航组件|纯血鸿蒙组件库 AUI

  • 2025-05-19
    广东
  • 本文字数:6057 字

    阅读完需:约 20 分钟

卡片导航组件|纯血鸿蒙组件库AUI

摘要:

卡片导航(A_CardNav):可设置导航数据(含文本、图标、路由),可设置为透明模式(适用于背景容器设置了颜色的情形),学习在鸿蒙中使用 Material Design Icons 图标库,。





一、组件调用方式

1.非透明模式

卡片导航组件的调用非常简单,只需要输入 A_CardNav ,然后给属性 data (导航数据)赋值即可。在 data 当中需要给文字、图标和跳转的路由赋值,如下图所示:

页面调用代码如下:

import { A_TitleBar } from '../aui/basic/A_TitleBar'import { A_CardNav } from '../aui/navigation/A_CardNav'import { ColorConstants } from '../constants/ColorConstants'import { FloatConstants } from '../constants/FloatConstants'import { GirdConstants } from '../constants/GirdConstants'import { WindowUtils } from '../utils/WindowUtils'
@Componentexport struct CardNav { @StorageLink('pageInfo') pageInfo: NavPathStack = new NavPathStack() @StorageLink('primaryColor') primaryColor: ResourceStr = ColorConstants.INFO @StorageLink('deviceType') deviceType: string = GirdConstants.DEVICE_SM
aboutToAppear() { WindowUtils.getInstance()?.setFullScreen() }
build() { Row() { Column() { // 标题栏 A_TitleBar({ text: '调用示例一' })
// 下拉容器 Scroll() { GridRow({ columns: { sm: GirdConstants.GRID_COLUMNS[0], md: GirdConstants.GRID_COLUMNS[1], lg: GirdConstants.GRID_COLUMNS[2] }, gutter: { x: GirdConstants.GRID_GUTTER, y: GirdConstants.GRID_GUTTER }, breakpoints: { reference: BreakpointsReference.WindowSize } }) {
GridCol({ span: 12 }) { A_CardNav({ data: [ { text: 'Java', icon: 'mdi-language-java', router: '' }, { text: 'Python', icon: 'mdi-language-python', router: '' }, { text: 'Vuetify', icon: 'cast-variant', router: 'OrderDetail/2' }, { text: '纯血鸿蒙', icon: 'mdi-tablet-cellphone', router: 'AccountPage' } ] }) } .margin({ top: FloatConstants.SPACE_TOP }) } .padding({ bottom:this.deviceType === GirdConstants.DEVICE_LG ? GirdConstants.ZERO : FloatConstants.SPACE_S }) } .scrollBar(BarState.Off) } .height(GirdConstants.FULL_PERCENT) } .alignItems(VerticalAlign.Top) .padding({ top: FloatConstants.SPACE_TOP, left:FloatConstants.SPACE_LEFT, right:FloatConstants.SPACE_RIGHT, bottom:this.deviceType === GirdConstants.DEVICE_LG ? GirdConstants.GRID_BOTTOM : FloatConstants.SPACE_BOTTOM }) .width(GirdConstants.FULL_PERCENT) .backgroundColor(ColorConstants.APP_BG) }}
复制代码

本地模拟器下浅色模式和深色模式运行效果如下:



2.透明模式

卡片导航组件放在一个有颜色背景上面,此时,无论深色模式还是浅色模式,文字和图标均始终显示为白色。只需要增加一个属性 alphaMode: true 即可,如下图所示:

二、在线排版

在会员页面或管理后台的页面当中选择一个页面,比如“首页”,然后点击“页面设计”。如下图所示:

现在“首页”是一个空页面,还没有任何组件。展开左侧组件库中的“导航组件”分组,将“卡片导航组件”拖拽到页面中,如下图所示:

默认会有一个初始化的配置数据,在页面设计预览器下平板、折叠屏和手机的浅色模式的效果如下:



切换到深色模式,效果如下:



选择右侧“组件设置”下的“卡片导航”组件,点击“配置数据”按钮,可以根据自己的业务需要,新增、删除或修改每一项配置,如下图所示:

可以设置导航文字和导航的图标,其中导航图标支持使用 mdi 图标库,可点击“图标库”图标,进入 Material Design Icons 官方的图标库,使用这里的图标库,将来生成纯血鸿蒙代码或者 Vuetify3 网页端代码的时候,都是兼容的。如下图所示:

搜索或选择需要的图标,在弹出的窗口中拷贝图标名称,如下图所示:

然后在导航图标这个地方保留“mdi-”的前缀,粘贴新的图标名称,就能应用新的图标,如下图所示:

路由这个地方我们可以保持为空(这个时候,点击的时候不会跳转页面);但是,如果路由不为空,那么我们一定要绑定一个真实存在的页面,如下图所示,绑定“发现”页,配置好数据后,点击“确认”按钮:

现在,切换到代码魔法页面,我们可以在侧栏菜单这里选择“纯血鸿蒙”,(可以切换为深色模式,看代码更舒适),然后点击“生成代码”,如下图所示:

在生成的鸿蒙项目中,展开特性层(features),选择 home 模块,找到 /src/main/ets/view 目录下的 HomeView.ets 页面,查看生成的代码,如下图所示:

如果希望卡片导航组件运行在有特殊颜色的背景容器之上,可以使用透明模式。现在我们再次进入到页面设计预览器页面,将透明模式的选项改为“是”,点击“保存设置”,如下图所示:

再次生成鸿蒙代码,发现 A_CardNav 组件里增加了一个“alphaMode: true”的属性,效果如下:

三、源码解析

卡片导航组件支持两个属性,一个是 data(导航数据),另外一个是 alphaMode(是否是透明模式,默认值是 false):

卡片导航数据 data 是一个数组 Array<NavigationModel>,其中导航 Model 的数据结构如下,含三个字段:导航的文字(text)、导航图标(icon)和跳转页面的路由(router)。

继续分析卡片导航组件 A_CardNav 的源码,在 aboutToAppear() 这个生命周期当中,对设备为折叠屏、平板和手机时的 padding、margin 和行高做了差异化的处理,以实现“一多”适配,如下图所示:

同时,对导航数据中的图标做了一些处理。在给图标传参的时候,可以是"mdi-"开头或“mdi_”开头,或者不带这个开头,组件会根据传参值做相应处理。如果不以"mdi-"开头或“mdi_”开头,则自动补全"mdi_"开头;如果以"mdi-"开头,则改为"mdi_"开头(因为鸿蒙中的资源文件不支持中横线“-”);如果以“mdi_”开头则保持现状。最后,再给图标加上资源路径前缀“app.media.”。因为在 Vuetify 和鸿蒙中对图标命名格式上的差异,使用 AI 极客站点生成 Vuetify 和鸿蒙代码时会自动处理它的差异,打包的资源图标会自动重命名为符合要求的名称。代码如下:

 this.compData.forEach(element => {      element.icon = 'app.media.' + (element.icon.startsWith('mdi-') || element.icon.startsWith('mdi_') ? '' : 'mdi_') + element.icon.replaceAll('-', '_')    })
复制代码

在 build 函数中,通过 ForEach 循环遍历导航数据。当设备为手机的类型时,图标和文字是上下排列(手机屏幕宽度有限,上下排列比较合理);当设备为折叠屏或平板的时候,图标和文字是左右排列。如下图所示:

当设备为手机时(this.deviceType === GirdConstants.DEVICE_SM),使用列组件(Column)包裹图标和文字,实现上下排列的效果:

点击跳转路由的代码如下:

   .onClick(() => {            if (item.router) {              // 跳转到新页面              const router = item.router              if (router.includes("/")) {                this.pageInfo.pushPathByName(router.substring(0, router.indexOf("/")),                  router.substring(router.indexOf("/") + 1))              } else {                this.pageInfo.pushPathByName(router, null)              }            }          })
复制代码

当设备为折叠屏或平板的时候,图标和文字通过行组件(Row)包裹,实现左右排列的效果,如下图所示:

卡片导航组件的完整源码如下:

/* * Copyright (c) 2024 AIGCoder.com(AI极客) * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
/** 调用示例一: A_CardNav({ data: [ { text: 'Java', icon: 'mdi-language-java', router: '' }, { text: 'Python', icon: 'mdi-language-python', router: '' }, { text: 'Vuetify', icon: 'cast-variant', router: 'OrderDetail/2' }, { text: '纯血鸿蒙', icon: 'mdi-tablet-cellphone', router: 'AccountPage' } ] })
调用示例二:透明模式 A_CardNav({ data: [ { text: 'Java', icon: 'mdi-language-java', router: '' }, { text: 'Python', icon: 'mdi-language-python', router: '' }, { text: 'Vuetify', icon: 'cast-variant', router: 'OrderDetail/2' }, { text: '纯血鸿蒙', icon: 'mdi-tablet-cellphone', router: 'AccountPage' } ], alphaMode: true }) */
import { ColorConstants } from "../../constants/ColorConstants"import { FloatConstants } from "../../constants/FloatConstants"import { GirdConstants } from "../../constants/GirdConstants"import { NavigationModel } from "../../models/NavigationModel"
/** * 【卡片导航】 * data:导航数据 * alphaMode:透明模式(适用于背景容器设置了颜色的情形) */@Componentexport struct A_CardNav { @Prop data: Array<NavigationModel> @Prop alphaMode?: boolean = false
@StorageLink('pageInfo') pageInfo: NavPathStack = new NavPathStack() @StorageLink('deviceType') deviceType: string = GirdConstants.DEVICE_SM @State compPadding: Length = '0vp' @State compMargin: Length = '12vp' @State compRowHeight: Length = '56vp' private compData: Array<NavigationModel> = this.data
aboutToAppear(): void { switch (this.deviceType){ case GirdConstants.DEVICE_MD: this.compPadding = '21vp' this.compMargin = '12vp' this.compRowHeight = '56vp' break case GirdConstants.DEVICE_LG: this.compPadding = '29vp' this.compMargin = '30vp' this.compRowHeight = '80vp' break case GirdConstants.DEVICE_SM: default: this.compPadding = '0vp' break } this.compData.forEach(element => { element.icon = 'app.media.' + (element.icon.startsWith('mdi-') || element.icon.startsWith('mdi_') ? '' : 'mdi_') + element.icon.replaceAll('-', '_') }) }
build() { Row() { ForEach(this.compData, (item: NavigationModel) => { if (this.deviceType === GirdConstants.DEVICE_SM) {//手机:上下排列 Column({ space: GirdConstants.EIGHT }) { Row() { Image($r(item.icon)) .width(FloatConstants.IMAGE_SIZE6) .height(FloatConstants.IMAGE_SIZE6) .fillColor(this.alphaMode ? Color.White : ColorConstants.FG_LEVEL1) } .width(FloatConstants.IMAGE_SIZE10) .height(FloatConstants.IMAGE_SIZE10) .alignSelf(ItemAlign.Center) .justifyContent(FlexAlign.Center) .borderRadius(FloatConstants.IMAGE_SIZE10) .backgroundColor(ColorConstants.CONTROL_BG_ALPHA)
Text(item.text) .fontSize(FloatConstants.FONT_SIZE_BODY_L) .fontColor(this.alphaMode ? Color.White : ColorConstants.FG_LEVEL1) } .onClick(() => { if (item.router) { // 跳转到新页面 const router = item.router if (router.includes("/")) { this.pageInfo.pushPathByName(router.substring(0, router.indexOf("/")), router.substring(router.indexOf("/") + 1)) } else { this.pageInfo.pushPathByName(router, null) } } }) } else {// 平板:左右排列 Row() { Image($r(item.icon)) .width(FloatConstants.IMAGE_SIZE9) .height(FloatConstants.IMAGE_SIZE9) .fillColor(this.alphaMode ? Color.White : ColorConstants.FG_LEVEL1) Text(item.text) .fontSize(FloatConstants.FONT_SIZE_BODY_L) .fontColor(this.alphaMode ? Color.White : ColorConstants.FG_LEVEL1) .margin({ left: this.compMargin }) } .width(GirdConstants.TWENTY_PERCENT) .height(this.compRowHeight) .alignSelf(ItemAlign.Center) .justifyContent(FlexAlign.Center) .borderRadius(FloatConstants.RADIUS_CARD) .backgroundColor(ColorConstants.CONTROL_BG_ALPHA) .onClick(() => { if (item.router) { // 跳转到新页面 const router = item.router if (router.includes("/")) { this.pageInfo.pushPathByName(router.substring(0, router.indexOf("/")), router.substring(router.indexOf("/") + 1)) } else { this.pageInfo.pushPathByName(router, null) } } }) } }, (item: NavigationModel, index: number) => index + JSON.stringify(item)) } .justifyContent(FlexAlign.SpaceBetween) .padding({ left: this.compPadding, right: this.compPadding }) .width(GirdConstants.FULL_PERCENT) }}
复制代码

四、源码下载

AIGCoder.com-AI极客

用户头像

还未添加个人签名 2025-04-29 加入

还未添加个人简介

评论

发布
暂无评论
卡片导航组件|纯血鸿蒙组件库AUI_鸿蒙_华哥的全栈次元舱_InfoQ写作社区