在 HarmonyOS6 中实现 Material Design 3 导航栏
文章目录一、什么是 Material Design 3二、Elevation 层级系统2.1 层级概念2.2 项目中的枚举定义2.3 Elevation 转换为 shadow 参数三、色彩系统3.1 色彩角色定义3.2 浅色与深色两套配色3.3 应用到标签栏四、主题切换4.1 切换逻辑4.2 Elevation 动态调节五、完整标签栏容器总结一、什么是 Material Design 3Material Design 3简称 M3是 Google 的设计系统最新版本。HarmonyOS 有自己的设计语言 HDS但很多开发者仍然选择 M3 风格来获得跨平台视觉一致性。M3 的两个核心机制Elevation层级通过阴影深度表达元素的空间层次阴影越深元素在视觉上悬浮越高Color Roles色彩角色一套完整的色彩命名规范每个颜色都有明确用途浅色/深色主题切换只需换一套色值不用改代码逻辑。二、Elevation 层级系统2.1 层级概念Elevation 用 dp 值表示元素的悬浮高度数值越大阴影越明显0dp 无阴影 贴在背景上 1dp 轻微阴影 轻微抬起 2dp 卡片阴影 卡片级别 4dp 导航阴影 导航栏级别推荐 8dp 弹窗阴影 对话框级别 16dp 模态阴影 全屏模态级别2.2 项目中的枚举定义exportenumMaterialElevation{NONE0,// 0dp - 无阴影RAISED1,// 1dp - 轻微抬起CARD2,// 2dp - 卡片NAVIGATION4,// 4dp - 导航栏底部标签栏推荐值DIALOG8,// 8dp - 对话框MODAL16,// 16dp - 模态窗口}2.3 Elevation 转换为 shadow 参数HarmonyOS 使用shadow属性实现阴影。在MaterialTabItem组件中Elevation 数值按以下公式映射到shadow参数Componentstruct MaterialTabItem{PropisActive:boolean;Proptab:TabItem;PropcolorScheme:MaterialColorScheme;Propelevation:number;// 接收父组件传入的 Elevation 值build(){Column(){// ...图标和文字...}.shadow({// 1dp 约等于 3px 模糊半径radius:this.elevation*3,// Elevation 越高透明度越低阴影越深上限 0.25color:rgba(0, 0, 0,${Math.min(0.05this.elevation*0.02,0.25)}),offsetX:0,offsetY:this.elevation*1.5// 垂直偏移与 Elevation 成正比})}}代码说明radius: elevation * 3让阴影随层级线性扩大层级越高阴影越柔和Math.min(0.05 elevation * 0.02, 0.25)控制阴影透明度设置上限0.25防止阴影过重offsetY: elevation * 1.5让阴影随层级向下偏移模拟光线从上方照射的效果。三、色彩系统3.1 色彩角色定义// entry/src/main/ets/types/TabBarTypes.etsexportinterfaceMaterialColorScheme{primary:ResourceColor;// 主色选中状态背景primaryVariant:ResourceColor;// 主色变体secondary:ResourceColor;// 次要色secondaryVariant:ResourceColor;background:ResourceColor;// 页面背景色surface:ResourceColor;// 卡片/标签栏背景色error:ResourceColor;// 错误色success:ResourceColor;warning:ResourceColor;onPrimary:ResourceColor;// 主色上的文字/图标颜色onSecondary:ResourceColor;onBackground:ResourceColor;// 背景上的文字颜色onSurface:ResourceColor;// 表面色上的文字颜色}代码说明以on开头的颜色表示放在该背景上的前景色。比如onPrimary是放在primary色背景上的文字颜色onSurface是放在surface色背景上的文字颜色。这种命名约定让颜色用途一目了然。3.2 浅色与深色两套配色exportconstMaterialLightColorScheme:MaterialColorScheme{primary:#6200EE,// 深紫色作为主色primaryVariant:#3700B3,secondary:#03DAC6,secondaryVariant:#018786,background:#FAFAFA,surface:#FFFFFF,error:#B00020,success:#4CAF50,warning:#FF9800,onPrimary:#FFFFFF,// 深紫背景上用白色文字onSecondary:#000000,onBackground:#000000,onSurface:#000000,};exportconstMaterialDarkColorScheme:MaterialColorScheme{primary:#BB86FC,// 浅紫色在深色背景上可读性好primaryVariant:#3700B3,secondary:#03DAC6,secondaryVariant:#03DAC6,background:#121212,// 深色背景surface:#1E1E1E,error:#CF6679,success:#81C784,warning:#FFB74D,onPrimary:#000000,// 浅紫背景上用黑色文字onSecondary:#000000,onBackground:#FFFFFF,onSurface:#FFFFFF,};代码说明深色模式下primary从深紫#6200EE换成浅紫#BB86FC原因是深色模式背景很深深紫在其上会显得不清晰onPrimary也相应从白色换为黑色保证对比度。3.3 应用到标签栏// MaterialTabItem 组件中的颜色使用build(){Column(){// 图标颜色选中时用 onPrimary未选中时用 onSurfaceSymbolGlyph(this.isActive?this.tab.activeIcon:this.tab.icon).fontSize(24).fontColor(this.isActive?[this.colorScheme.onPrimary]// 选中主色背景上的文字色:[this.colorScheme.onSurface]// 未选中表面色上的文字色)// 图标缩放动画选中时放大 10%.scale({x:this.isActive?1.1:1,y:this.isActive?1.1:1,}).animation({duration:200,curve:Curve.EaseOut})// 标签文字Text(this.tab.title).fontSize(12).fontColor(this.isActive?this.colorScheme.onPrimary:this.colorScheme.onSurface).fontWeight(this.isActive?FontWeight.Medium:FontWeight.Normal).margin({top:4})// 选中指示条宽度从 0 动画展开到 32Row().width(this.isActive?32:0).height(3).backgroundColor(this.colorScheme.onPrimary).borderRadius(1.5).margin({top:4}).animation({duration:200,curve:Curve.FastOutSlowIn})}.width(64).height(56).backgroundColor(this.isActive?this.colorScheme.primary:Color.Transparent).borderRadius(16)// ...shadow 属性见上文}代码说明选中状态下整个Column背景变为primary色图标和文字颜色切换为onPrimary形成色彩组合一致的选中效果指示条宽度从0到32配合.animation()ArkUI 会自动插值生成展开动画Curve.FastOutSlowIn是 M3 推荐的动画曲线起步快、收尾慢符合物理直觉。四、主题切换4.1 切换逻辑EntryComponentstruct MaterialTabsDemo{StateisDarkMode:booleanfalse;StatecolorScheme:MaterialColorSchemeMaterialLightColorScheme;// 点击主题切换按钮时调用privatetoggleTheme(){// 用 animateTo 包裹状态更新让颜色变化有过渡动画animateTo({duration:300,curve:Curve.EaseInOut},(){this.isDarkMode!this.isDarkMode;this.colorSchemethis.isDarkMode?MaterialDarkColorScheme:MaterialLightColorScheme;});}}代码说明整个颜色方案是一个对象引用切换主题只需把colorScheme指向另一个预设对象所有依赖它的子组件会自动重新渲染。用animateTo包裹赋值操作让颜色变化有平滑过渡。4.2 Elevation 动态调节本项目提供了一个 Elevation 选择器可以实时预览不同阴影深度的效果// Elevation 选择器 UIForEach([{label:0,value:MaterialElevation.NONE},{label:1,value:MaterialElevation.RAISED},{label:2,value:MaterialElevation.CARD},{label:4,value:MaterialElevation.NAVIGATION},{label:8,value:MaterialElevation.DIALOG},],(item:ElevationItem){// ElevationItem 是文件顶部定义的 interfaceText(item.label).fontSize(13).fontWeight(this.elevationitem.value?FontWeight.Medium:FontWeight.Normal).fontColor(this.elevationitem.value?this.colorScheme.primary:this.colorScheme.onSurface).padding({left:8,right:8,top:4,bottom:4}).borderRadius(12).backgroundColor(this.elevationitem.value?this.colorScheme.primary:Color.Transparent).onClick((){animateTo({duration:200},(){this.elevationitem.value;});})})代码说明这里用到了本地定义的interface ElevationItem而不是Recordstring, number原因是 ArkTS 规范禁止在回调函数类型声明处直接使用对象字面量类型必须先声明为具名接口每个 Elevation 选项在点击后通过animateTo使阴影变化有动画效果。五、完整标签栏容器// 底部 Material 标签栏容器Row(){ForEach(this.tabs,(tab:TabItem,index:number){MaterialTabItem({isActive:this.currentIndexindex,tab:tab,colorScheme:this.colorScheme,elevation:this.elevation}).onClick((){this.switchTab(index);})})}.width(100%).height(64).padding({bottom:8}).backgroundColor(this.colorScheme.surface)// 标签栏背景用 surface 色.justifyContent(FlexAlign.SpaceEvenly).shadow({radius:12,// 深色模式下阴影更深浅色模式下更轻color:this.isDarkMode?rgba(0, 0, 0, 0.4):rgba(0, 0, 0, 0.08),offsetX:0,offsetY:-4// 向上偏移阴影出现在标签栏顶部边缘}).expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.BOTTOM])代码说明offsetY: -4让阴影出现在标签栏上方产生内容从下方滑入的层次感深色模式下阴影透明度从0.08提高到0.4因为深色背景上浅色阴影几乎不可见。总结Material Design 3 的精髓在于系统性颜色不是随手选的而是有角色分工阴影不是装饰性的而是有层级含义。在 HarmonyOS 里把这套规范落地核心工作就两件事——把 Elevation 映射成shadow参数把色彩角色映射成一个可以整体切换的配色对象。把这两个部分搭建好之后浅色/深色主题切换、阴影层级调整都只是换一个变量的事整个代码结构会变得非常清晰好维护。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2542077.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!