news 2026/7/27 8:31:13

HarmonyOS7 ArkUI 视频列表 - 封面卡片、播放量、关注按钮实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS7 ArkUI 视频列表 - 封面卡片、播放量、关注按钮实战

文章目录

      • 前言
      • 从界面倒推代码
      • 交互入口在哪里
      • 代码里的重点
        • 片段 1:`toggleFollow(id: number) {`
        • 片段 2:`likesDisplay(count: number): string {`
      • 使用方式
      • 完整代码
      • 收个尾

前言

这篇不讲空概念,直接从页面代码拆。能复用的不是某个颜色值,而是状态、派生数据和布局之间的组织方式。
它的主线是视频列表,细节落在封面卡片、播放量、关注按钮。这些细节刚好能把页面状态、用户操作和组件刷新串起来。

从界面倒推代码

VideoFeedPage不是一个只展示静态内容的页面。它会根据用户点击、输入、切换或计时来改变界面,所以阅读代码时可以先抓三条线:

观察点在这个案例里的表现

| 页面主题 |视频列表|
| 主要文案 |教程,3天前,设计,1天前,创意,5天前|
| 常用组件 |Column,ForEach,Row,Scroll,Stack,Text|
| 适合练习 | 状态驱动 UI、条件样式、列表渲染、事件回调 |

交互入口在哪里

ArkUI 的页面刷新依赖状态变化。下面这些@State字段就是页面的“开关”和“数据源”,不用手动找 DOM,也不用自己通知某个控件刷新。

状态字段类型我会怎么理解它
videosVideoItem_75fu[]列表数据源,通常会被ForEach消费
activeCategorystring当前选中项,决定高亮和内容切换
searchTextstring用户输入值,参与计算或提交

一个经验:先把@State看完,再看build(),页面逻辑会清楚很多。否则很容易被一长串布局代码带偏。

代码里的重点

片段 1:toggleFollow(id: number) {

这段代码承担的是页面里的“判断”或“动作”,把它从布局里抽出来后,build()会清爽很多。后面要加新条件,也不会到处翻 UI 代码。

toggleFollow(id:number){this.videos=this.videos.map(v=>{if(v.id===id){v.isFollowed=!v.isFollowedreturnv}returnv})}

片段 2:likesDisplay(count: number): string {

这段代码承担的是页面里的“判断”或“动作”,把它从布局里抽出来后,build()会清爽很多。后面要加新条件,也不会到处翻 UI 代码。

likesDisplay(count:number):string{returncount>=10000?(count/10000).toFixed(1)+'万':count+''}

使用方式

把下面代码放进 ArkTS 页面文件中即可运行。用于正式项目时,我会继续把数据模型、卡片 Builder 和页面事件拆出去,页面文件只负责组合。

建议练习顺序:先改状态字段 -> 再改交互事件 -> 最后调整 UI 样式 检查重点:点击是否刷新、列表 key 是否稳定、条件样式是否集中管理
这份代码可以继续扩展的方向
  • 把模拟数据替换成接口数据
  • 抽出复用卡片组件
  • 增加空状态和异常状态
  • 补充深色模式或主题色适配
  • 对输入类场景增加校验提示

完整代码

// VideoFeedPage - 视频列表(封面卡片、播放量、关注按钮)interfaceVideoItem_75fu{id:numbertitle:stringauthor:stringavatar:stringcoverColor:ResourceColor coverEmoji:stringviews:stringlikes:numberduration:stringcategory:stringisFollowed:booleanpublishTime:string}interfaceCategoryTab_i98l{key:stringlabel:string}@Entry@Componentstruct VideoFeedPage{@Statevideos:VideoItem_75fu[]=[{id:1,title:'HarmonyOS ArkTS 零基础入门教程 | 手把手教你开发第一个鸿蒙应用',author:'鸿蒙技术派',avatar:'🦁',coverColor:'#1E3A5F',coverEmoji:'📱',views:'18.6万',likes:3420,duration:'23:45',category:'教程',isFollowed:false,publishTime:'3天前'},{id:2,title:'UI设计神技 | 10个让界面瞬间高级的小技巧,99%的人不知道',author:'UI大魔王',avatar:'🎨',coverColor:'#3D1A78',coverEmoji:'✨',views:'45.2万',likes:8900,duration:'12:30',category:'设计',isFollowed:true,publishTime:'1天前'},{id:3,title:'用代码画出星空 | p5.js 粒子系统实战演示',author:'代码艺术家',avatar:'🌟',coverColor:'#0A1628',coverEmoji:'🌌',views:'7.3万',likes:1580,duration:'18:22',category:'创意',isFollowed:false,publishTime:'5天前'},{id:4,title:'2024 最值得学的前端框架大盘点,别再迷茫了!',author:'前端老炮儿',avatar:'💻',coverColor:'#1A3A1A',coverEmoji:'🚀',views:'32.1万',likes:6200,duration:'15:10',category:'教程',isFollowed:true,publishTime:'2天前'},{id:5,title:'从0到1搭建完整的后台管理系统 | Vue3 + TypeScript 实战',author:'全栈工程师小明',avatar:'⚡',coverColor:'#3A1A1A',coverEmoji:'🛠️',views:'9.8万',likes:2100,duration:'45:00',category:'实战',isFollowed:false,publishTime:'1周前'},{id:6,title:'设计师眼中的好代码 | 前端与UI如何高效协作',author:'协作达人',avatar:'🤝',coverColor:'#1A2A3A',coverEmoji:'💡',views:'5.6万',likes:890,duration:'20:15',category:'经验',isFollowed:false,publishTime:'4天前'}]@StateactiveCategory:string='推荐'@StatesearchText:string=''privatecategories:CategoryTab_i98l[]=[{key:'推荐',label:'🔥 推荐'},{key:'教程',label:'📚 教程'},{key:'设计',label:'🎨 设计'},{key:'实战',label:'⚡ 实战'},{key:'创意',label:'✨ 创意'}]toggleFollow(id:number){this.videos=this.videos.map(v=>{if(v.id===id){v.isFollowed=!v.isFollowedreturnv}returnv})}likesDisplay(count:number):string{returncount>=10000?(count/10000).toFixed(1)+'万':count+''}getfilteredVideos():VideoItem_75fu[]{if(this.activeCategory==='推荐')returnthis.videosreturnthis.videos.filter(v=>v.category===this.activeCategory)}@BuildervideoCard(video:VideoItem_75fu){Column({space:0}){// 视频封面Stack({alignContent:Alignment.Bottom}){// 封面背景Column(){Text(video.coverEmoji).fontSize(60)}.width('100%').height(180).backgroundColor(video.coverColor).justifyContent(FlexAlign.Center).borderRadius({topLeft:12,topRight:12})// 时长标签Row(){Blank()Text(video.duration).fontSize(12).fontColor('#FFFFFF').padding({left:8,right:8,top:3,bottom:3}).backgroundColor('#000000AA').borderRadius(6)}.width('100%').padding({right:10,bottom:10})// 播放按钮(圆形半透明)Circle({width:50,height:50}).fill('#00000060').position({x:'50%',y:'50%'}).translate({x:-25,y:-25-10})Text('▶').fontSize(18).fontColor('#FFFFFF').position({x:'50%',y:'50%'}).translate({x:-8,y:-8-10})}.width('100%')// 视频信息Row({space:10}){// 作者头像Text(video.avatar).fontSize(24).width(40).height(40).textAlign(TextAlign.Center).backgroundColor('#F3F4F6').borderRadius(20)Column({space:4}){Text(video.title).fontSize(14).fontColor('#111827').maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis}).lineHeight(20)Row({space:6}){Text(video.author).fontSize(12).fontColor('#6B7280')Text('·').fontSize(12).fontColor('#D1D5DB')Text(video.views+'次播放').fontSize(12).fontColor('#9CA3AF')Text('·').fontSize(12).fontColor('#D1D5DB')Text(video.publishTime).fontSize(12).fontColor('#9CA3AF')}}.layoutWeight(1).alignItems(HorizontalAlign.Start)}.width('100%').padding({left:12,right:12,top:10,bottom:6})// 底部互动栏Row({space:0}){Row({space:6}){Text('👍').fontSize(14)Text(this.likesDisplay(video.likes)).fontSize(13).fontColor('#6B7280')}.layoutWeight(1)Row({space:6}){Text('💬').fontSize(14)Text('评论').fontSize(13).fontColor('#6B7280')}.layoutWeight(1)Row({space:6}){Text('↗️').fontSize(14)Text('分享').fontSize(13).fontColor('#6B7280')}.layoutWeight(1)// 关注按钮Text(video.isFollowed?'✓ 已关注':'+ 关注').fontSize(13).fontColor(video.isFollowed?'#6B7280':'#FFFFFF').padding({left:14,right:14,top:6,bottom:6}).backgroundColor(video.isFollowed?'#F3F4F6':'#3B82F6').borderRadius(16).onClick(()=>this.toggleFollow(video.id))}.width('100%').padding({left:12,right:12,top:4,bottom:12})}.width('100%').backgroundColor('#FFFFFF').borderRadius(12).shadow({radius:6,color:'#00000010',offsetX:0,offsetY:2}).clip(true)}build(){Column(){// 顶部搜索栏Row({space:10}){Row({space:8}){Text('🔍').fontSize(16).fontColor('#9CA3AF')Text('搜索视频、创作者...').fontSize(14).fontColor('#9CA3AF')Blank()}.layoutWeight(1).height(40).padding({left:14,right:14}).backgroundColor('#F3F4F6').borderRadius(20)Text('🔔').fontSize(22)Text('👤').fontSize(22)}.width('100%').padding({left:16,right:16,top:50,bottom:12}).backgroundColor('#FFFFFF')// 分类 TabScroll(){Row({space:8}){ForEach(this.categories,(cat:CategoryTab_i98l)=>{Text(cat.label).fontSize(14).fontColor(this.activeCategory===cat.key?'#FFFFFF':'#374151').padding({left:16,right:16,top:8,bottom:8}).backgroundColor(this.activeCategory===cat.key?'#3B82F6':'#F3F4F6').borderRadius(20).onClick(()=>{this.activeCategory=cat.key})})}.padding({left:16,right:16,bottom:10,top:4})}.scrollable(ScrollDirection.Horizontal).backgroundColor('#FFFFFF').border({width:{bottom:0.5},color:'#F3F4F6'})// 视频列表Scroll(){Column({space:14}){ForEach(this.filteredVideos,(video:VideoItem_75fu)=>{this.videoCard(video)})}.padding({left:16,right:16,top:14,bottom:30})}.layoutWeight(1).backgroundColor('#F9FAFB')}.width('100%').height('100%').backgroundColor('#F9FAFB')}}

收个尾

这个案例可以当成一个小模板:先把页面会变的东西放进状态,再用函数或 Builder 处理重复逻辑,最后让布局只关心展示。写 HarmonyOS7 页面时,这个顺序通常比一上来堆 UI 更稳。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/27 8:31:02

PyPI供应链攻击深度解析:从LiteLLM恶意包事件看开源依赖安全

1. 事件概述:LiteLLM PyPI包安全事件深度解析最近在AI开发圈和开源安全领域,一个事件引发了不小的震动:一个名为“litellm”的Python包在PyPI(Python Package Index)官方仓库中被发现植入了恶意代码。如果你最近执行过…

作者头像 李华
网站建设 2026/7/27 8:29:03

解决ssh的rviz显示问题

sudo apt update sudo apt install -y ros-noetic-rviz 三、解决你 OK3588 MobaXterm 远程 xcb 报错(重点) 补齐全部 XCB/Qt 图形依赖(ARM 板必装) bash 运行 sudo apt install -y libxcb1 libxcb-cursor0 libxcb-xinerama0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 l…

作者头像 李华
网站建设 2026/7/27 8:26:57

AI辅助学术写作:人机协同的认知革命与实践指南

1. 当AI成为学术伙伴:重新定义毕业论文写作范式 最近在指导本科生论文时,我注意到一个有趣的现象:学生们不再像往年那样抱怨"查文献查到眼瞎",而是开始讨论哪个AI工具更"懂学术"。这让我想起十年前自己写硕士…

作者头像 李华
网站建设 2026/7/27 8:24:41

KVM主题:XML配置热更新与版本管理实践

KVM主题:XML配置热更新与版本管理实践 在虚拟化技术日益普及的今天,KVM(Kernel-based Virtual Machine)作为Linux内核中的一个模块,为虚拟机管理提供了强大的支持。对于运行在KVM之上的虚拟机而言,其配置文…

作者头像 李华