HarmonyOS PC实战系列之应用图标的视觉设计——圆角方块、更新角标与评分展示
文章目录圆角方块尺寸和弧度的选择阴影颜色用图标主色更新角标Stack 叠加评分展示数字 星完整代码角标超出边界的实现小结应用桌面这种场景用户扫视的时间很短视觉关注点大多数落在图标上。图标设计的质量直接决定整个页面的第一印象。这篇拆解 PC 端应用图标的三个视觉细节圆角方块的尺寸和弧度、更新角标的 Stack 实现、应用评分的展示方式。单个细节都不复杂但组合在一起就是整体感的差距。圆角方块尺寸和弧度的选择PC 端应用图标的标准尺寸是 64×64vpborderRadius 16vp弧度约为尺寸的 25%。这个比例在视觉上很舒适比苹果的 iOS 图标稍方比 Android 的图标稍圆。Column(){Text(app.icon).fontSize(32)}.width(64).height(64).borderRadius(16).backgroundColor(app.color).justifyContent(FlexAlign.Center)图标内容emoji 或实际 SVG的字号是图标尺寸的 50%也就是 32px。比例偏小时图标显得空比例偏大时显得拥挤。阴影颜色用图标主色图标阴影不用纯黑用图标主色的半透明.shadow({radius:8,color:${app.color}30,// 主色 19% 透明度offsetY:4})这样每个图标的阴影颜色和自身颜色协调整个桌面看起来丰富而不杂乱。用纯黑阴影在彩色图标下反而显得脏。更新角标Stack 叠加角标红点叠在图标右上角用Stack实现Stack({alignContent:Alignment.TopEnd}){// 底层图标Column(){Text(app.icon).fontSize(32)}.width(64).height(64).borderRadius(16).backgroundColor(app.color).justifyContent(FlexAlign.Center)// 上层红点角标if(app.hasUpdate){Circle({width:12,height:12}).fill(#EF4444).border({width:2,color:Color.White}).offset({x:4,y:-4})// 向右上方偏移超出图标边界}}Alignment.TopEnd让角标默认对齐右上角.offset({ x: 4, y: -4 })让它稍微超出图标边界这是 iOS 风格角标的标准做法。白色描边让角标和背景颜色脱开防止颜色重叠看不清。评分展示数字 星评分用数字如 4.8而不是填充星星图标。原因应用图标下方空间很小填充 5 颗星太挤一个数字加一个星号更简洁信息密度更高。Row({space:2}){Text(★).fontSize(9).fontColor(#F59E0B)Text(${app.rating.toFixed(1)}).fontSize(10).fontColor(#6B7280)}字号要小不能抢占应用名称的视觉权重。完整代码interfaceAppItem{id:numbername:stringcategory:stringicon:stringcolor:stringhasUpdate:booleanrating:numberisNew:boolean}EntryComponentstruct PcAppIconPage{StateselectedId:number-1apps:AppItem[][{id:1,name:浏览器,category:工具,icon:,color:#3B82F6,hasUpdate:false,rating:4.8,isNew:false},{id:2,name:文件管理,category:系统,icon:,color:#10B981,hasUpdate:true,rating:4.6,isNew:false},{id:3,name:备忘录,category:效率,icon:,color:#F59E0B,hasUpdate:false,rating:4.7,isNew:false},{id:4,name:日历,category:效率,icon:,color:#8B5CF6,hasUpdate:true,rating:4.5,isNew:false},{id:5,name:代码编辑器,category:效率,icon:,color:#1D4ED8,hasUpdate:false,rating:4.9,isNew:true},{id:6,name:相册,category:媒体,icon:️,color:#EC4899,hasUpdate:false,rating:4.8,isNew:false},{id:7,name:音乐,category:媒体,icon:,color:#6366F1,hasUpdate:true,rating:4.7,isNew:false},{id:8,name:天气,category:工具,icon:️,color:#06B6D4,hasUpdate:false,rating:4.6,isNew:true},{id:9,name:AppGallery,category:系统,icon:,color:#CF1322,hasUpdate:true,rating:4.8,isNew:false},{id:10,name:终端,category:系统,icon:⬛,color:#111827,hasUpdate:false,rating:4.8,isNew:false},]BuilderbadgeArea(app:AppItem){// 三种角标更新红点、NEW标签、无角标if(app.hasUpdate){Circle({width:12,height:12}).fill(#EF4444).border({width:2,color:Color.White}).offset({x:4,y:-4})}elseif(app.isNew){Text(NEW).fontSize(8).fontColor(Color.White).fontWeight(FontWeight.Bold).padding({left:4,right:4,top:2,bottom:2}).backgroundColor(#10B981).borderRadius(6).border({width:1.5,color:Color.White}).offset({x:4,y:-4})}}BuilderappIcon(app:AppItem){Column({space:6}){// 图标Stack实现角标叠加Stack({alignContent:Alignment.TopEnd}){Column(){Text(app.icon).fontSize(32)}.width(64).height(64).borderRadius(16).backgroundColor(app.color).justifyContent(FlexAlign.Center).shadow({radius:this.selectedIdapp.id?16:8,color:${app.color}${this.selectedIdapp.id?50:25},offsetY:this.selectedIdapp.id?8:4}).scale({x:this.selectedIdapp.id?1.08:1.0,y:this.selectedIdapp.id?1.08:1.0}).animation({duration:150,curve:Curve.EaseOut})this.badgeArea(app)}.width(72)// 比图标稍宽给超出边界的角标留空间// 应用名Text(app.name).fontSize(11).fontColor(#374151).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis}).width(72).textAlign(TextAlign.Center)// 评分Row({space:2}){Text(★).fontSize(9).fontColor(#F59E0B)Text(app.rating.toFixed(1)).fontSize(10).fontColor(#9CA3AF)}.justifyContent(FlexAlign.Center)}.alignItems(HorizontalAlign.Center).padding({top:12,bottom:12}).onClick((){this.selectedIdthis.selectedIdapp.id?-1:app.id})}BuilderdesignNote(title:string,desc:string){Column({space:4}){Text(title).fontSize(13).fontWeight(FontWeight.Medium).fontColor(#374151)Text(desc).fontSize(12).fontColor(#6B7280).lineHeight(18)}.padding(12).backgroundColor(#F9FAFB).borderRadius(10).border({width:1,color:#E5E7EB}).alignItems(HorizontalAlign.Start).width(100%)}build(){Scroll(){Column({space:24}){// 标题Column({space:4}){Text(应用图标视觉设计).fontSize(22).fontWeight(FontWeight.Bold).fontColor(#111827)Text(点击图标查看选中状态效果).fontSize(14).fontColor(#6B7280)}.alignItems(HorizontalAlign.Start).width(100%)// 图标展示Flex({wrap:FlexWrap.Wrap,alignContent:FlexAlign.Start}){ForEach(this.apps,(app:AppItem){this.appIcon(app)})}.width(100%).padding(16).backgroundColor(Color.White).borderRadius(16).shadow({radius:8,color:#0A000000})// 设计说明Column({space:12}){Text(设计细节说明).fontSize(16).fontWeight(FontWeight.Bold).fontColor(#111827)this.designNote(图标尺寸与圆角,64×64vpborderRadius 16vp约图标尺寸的25%。图标内容字号32px占图标面积50%。)this.designNote(阴影颜色,使用图标主色 透明度约19%不用纯黑阴影。选中状态阴影加深到31%半径增大。)this.designNote(角标类型,红点角标表示有更新12vp红圆绿色NEW标签表示新应用。两者都有白色描边防止与背景混淆。)this.designNote(评分展示,数字星号不用填充5颗星太占空间。字号10px颜色灰色视觉权重低于应用名称。)this.designNote(选中动效,点击时图标微缩放1.08倍阴影加深animation过渡150ms。再次点击取消选中。)}.alignItems(HorizontalAlign.Start)}.padding({left:32,right:32,top:32,bottom:32}).constraintSize({minWidth:600,maxWidth:900}).margin({left:auto,right:auto})}.width(100%).height(100%).backgroundColor(#F9FAFB)}}角标超出边界的实现Circle角标用.offset({ x: 4, y: -4 })超出图标边界模拟 iOS 风格。但这样角标会被Stack容器裁剪。解决方法让Stack的宽度比图标大几个像素给角标留出空间Stack({alignContent:Alignment.TopEnd}){Column()// 64vp 图标.width(64)Circle()// 12vp 角标offset 超出 4px.offset({x:4,y:-4})}.width(72)// Stack 宽度 图标宽度 角标超出量这样角标不会被裁剪又能保持和图标的视觉关联。小结图标设计的几个关键数字尺寸 64vp圆角 16vp25%内容字号 32px50%阴影透明度 19%~31%角标尺寸 12vp角标描边 2vp。这套数字关系在应用桌面场景经过反复验证拿来就能用。