
文章目录前言置顶大卡Stack 实现文字压图普通行图左文右的经典结构完整示例PC端新闻视觉层次页Stack vs Row选型逻辑圆角与 clip写在最后前言资讯 App 里第一条新闻永远是最显眼的——大封面图、标题叠在图片上、字号更大。后面的普通条目则是小缩略图配文字列表。这种差异化不只是好看而是信息层级的视觉体现第一条是今天最重要的内容其他条目是候选内容。PC 端做这个效果核心是两种不同的布局结构置顶卡片用 Stack 图层叠加普通行用 Row 左图右文。这篇文章把这两种结构拆开来讲。置顶大卡Stack 实现文字压图Stack 允许多个子组件在同一位置叠加后声明的子组件显示在上层。置顶卡片的结构是背景图底层→ 半透明渐变遮罩中层→ 文字信息顶层。Stack({alignContent:Alignment.BottomStart}){// 底层背景色块或图片Column().width(100%).height(200).backgroundColor(#1E3A5F).borderRadius(12)// 中层渐变遮罩让文字更可读Column().width(100%).height(120).linearGradient({direction:GradientDirection.Top,colors:[[rgba(0,0,0,0.7),0],[rgba(0,0,0,0),1]]})// 顶层文字信息Column({space:8}){Text(置顶).fontSize(11).fontColor(#FCD34D)Text(HarmonyOS NEXT 正式发布).fontSize(18).fontColor(Color.White).fontWeight(FontWeight.Bold)Text(华为 · 10分钟前).fontSize(12).fontColor(rgba(255,255,255,0.7))}.padding({left:16,right:16,bottom:16})}.width(100%).height(200).clip(true)// 裁剪超出圆角的内容.borderRadius(12)alignContent: Alignment.BottomStart让文字默认对齐到左下角。clip(true)确保圆角裁剪对所有子层都生效。普通行图左文右的经典结构普通条目是 Row 布局左侧缩略图固定宽度右侧信息列layoutWeight(1)弹性填满Row({space:12}){// 左侧缩略图Stack(){RoundRect({width:72,height:72,radiusWidth:8,radiusHeight:8}).fill(#F3F4F6)Text(news.emoji).fontSize(28)}.width(72).height(72)// 右侧信息Column({space:6}){Text(news.title).fontSize(14).fontColor(#111827).fontWeight(FontWeight.Medium).maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis})Row({space:8}){Text(news.source).fontSize(12).fontColor(#6B7280)Text(news.time).fontSize(11).fontColor(#9CA3AF)}}.layoutWeight(1).alignItems(HorizontalAlign.Start)}完整示例PC端新闻视觉层次页完整示例PcNewsCardPage.etsimport{router}fromkit.ArkUIinterfaceNewsItem{id:numbertitle:stringdesc:stringsource:stringtime:stringcategory:stringemoji:stringbgColor:stringisTop:booleanreadCount:number}EntryComponentstruct PcNewsCardPage{StatehoveredId:number-1privatenewsList:NewsItem[][{id:1,title:HarmonyOS NEXT 正式发布全面进入鸿蒙时代,desc:华为正式宣布新一代鸿蒙操作系统正式商用标志着全面去安卓化完成生态建设进入新阶段。,source:华为官方,time:10分钟前,category:科技,emoji:,bgColor:#1E3A5F,isTop:true,readCount:12600},{id:2,title:ArkUI 4.0 新特性解读动效系统全面升级,desc:新版本带来弹簧动画、路径跟随动画等新能力。,source:开发者社区,time:1小时前,category:开发,emoji:✨,bgColor:#F3F4F6,isTop:false,readCount:5600},{id:3,title:鸿蒙 PC 端适配窗口管理与多任务实战,desc:详解 PC 端窗口自由拖拽、分屏多任务的实现思路。,source:技术博客,time:2小时前,category:开发,emoji:️,bgColor:#F3F4F6,isTop:false,readCount:4200},{id:4,title:鸿蒙生态应用突破十万覆盖主流场景,desc:金融、出行、购物等核心场景已全面覆盖生态建设取得里程碑进展。,source:鸿蒙生态,time:3小时前,category:产品,emoji:,bgColor:#F3F4F6,isTop:false,readCount:8900},{id:5,title:智能家居设备接入鸿蒙分布式框架全记录,desc:从设备注册到状态同步完整的开发流程记录。,source:极客之家,time:5小时前,category:开发,emoji:,bgColor:#F3F4F6,isTop:false,readCount:3100},]privategetTopNews():NewsItem{constlist:NewsItem[]this.newsList??[]consttoplist.find((n:NewsItem)n.isTop)returntop??list[0]??{id:0,title:,desc:,source:,time:,category:,emoji:,bgColor:#1E3A5F,isTop:false,readCount:0}}privategetNormalNews():NewsItem[]{constlist:NewsItem[]this.newsList??[]returnlist.filter((n:NewsItem)!n.isTop)}BuildertopCard(news:NewsItem){Stack({alignContent:Alignment.BottomStart}){// 背景色块Column().width(100%).height(200).backgroundColor(news.bgColor).borderRadius(12)// 大 emoji 装饰Text(news.emoji).fontSize(80).opacity(0.25).position({x:55%,y:20})// 渐变遮罩Column().width(100%).height(140).linearGradient({direction:GradientDirection.Top,colors:[[rgba(0,0,0,0.75),0],[rgba(0,0,0,0),1]]})// 文字内容Column({space:8}){Row({space:6}){Text(置顶).fontSize(10).fontColor(#FCD34D).backgroundColor(rgba(251,191,36,0.2)).borderRadius(4).padding({left:6,right:6,top:2,bottom:2})Text(news.category).fontSize(10).fontColor(rgba(255,255,255,0.8)).backgroundColor(rgba(255,255,255,0.15)).borderRadius(4).padding({left:6,right:6,top:2,bottom:2})}Text(news.title).fontSize(18).fontColor(Color.White).fontWeight(FontWeight.Bold).maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis})Text(news.desc).fontSize(12).fontColor(rgba(255,255,255,0.7)).maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis})Row({space:8}){Text(news.source).fontSize(12).fontColor(rgba(255,255,255,0.6))Text(·).fontSize(12).fontColor(rgba(255,255,255,0.4))Text(news.time).fontSize(12).fontColor(rgba(255,255,255,0.6))Blank()Text(${(news.readCount/1000).toFixed(1)}k).fontSize(11).fontColor(rgba(255,255,255,0.6))}.width(100%)}.padding({left:16,right:16,bottom:16}).width(100%)}.width(100%).clip(true).borderRadius(12).shadow({radius:8,color:${news.bgColor}40,offsetY:4})}BuildernormalCard(news:NewsItem){Row({space:12}){// 缩略图Stack(){Circle({width:64,height:64}).fill(#F3F4F6)Text(news.emoji).fontSize(28)}.width(64).height(64).borderRadius(8)// 信息列Column({space:6}){Text(news.title).fontSize(14).fontColor(#111827).fontWeight(FontWeight.Medium).maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis})Text(news.desc).fontSize(12).fontColor(#6B7280).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})Row({space:8}){Text(news.category).fontSize(10).fontColor(#3B82F6).backgroundColor(#EFF6FF).borderRadius(4).padding({left:5,right:5,top:1,bottom:1})Text(news.source).fontSize(11).fontColor(#9CA3AF)Text(news.time).fontSize(11).fontColor(#9CA3AF)Blank()Text(${news.readCount999?(news.readCount/1000).toFixed(1)k:news.readCount}).fontSize(11).fontColor(#9CA3AF)}.width(100%)}.layoutWeight(1).alignItems(HorizontalAlign.Start)}.width(100%).padding({left:20,right:20,top:14,bottom:14}).backgroundColor(this.hoveredIdnews.id?#F9FAFB:Color.White).border({width:{bottom:1},color:#F9FAFB}).onHover((isHover){this.hoveredIdisHover?news.id:-1}).animation({duration:150,curve:Curve.EaseOut})}build(){Scroll(){Column({space:0}){// 置顶大卡片Column(){this.topCard(this.getTopNews())}.padding({left:16,right:16,top:20,bottom:16}).backgroundColor(Color.White)// 分隔线Row(){Text(最新资讯).fontSize(13).fontColor(#6B7280).fontWeight(FontWeight.Medium)}.width(100%).padding({left:20,right:20,top:12,bottom:8}).backgroundColor(#F9FAFB)// 普通新闻列表Column({space:0}){ForEach(this.getNormalNews(),(news:NewsItem){this.normalCard(news)})}.backgroundColor(Color.White)}}.width(100%).height(100%).scrollBar(BarState.Off).backgroundColor(#F9FAFB)}}Stack vs Row选型逻辑Stack 的核心能力是图层叠加多个子组件在同一位置堆叠通过alignContent控制对齐通过position/offset精确定位。适合用 Stack 的场景文字叠在图片上封面图标题角标图片右上角数字遮罩层半透明蒙层适合用 Row 的场景元素横向并排图左文右元素有明确的空间分工置顶大卡片属于第一类必须用 Stack普通行属于第二类Row 更合适。圆角与 clipStack 给子组件设borderRadius时注意要在 Stack 上加.clip(true)才能让圆角真正裁剪内部子组件。否则背景色块有圆角但子组件比如遮罩层可能在圆角处溢出。写在最后置顶大卡和普通行的差异化设计本质上是在用视觉语言传达信息权重。Stack 给了我们把文字叠在图片上的能力Row 给了我们清晰的横向分区。两种结构各司其职组合起来就是完整的资讯列表视觉方案。