HarmonyOS7 页面切换动画:自己手搓一个 Tab 过渡效果 📅 2026/7/24 21:10:21 文章目录前言为什么不用原生 Tabs核心实现状态定义Tab 栏的实现内容区域滑动方向的判断优化建议写在最后前言ArkUI 自带的Tabs组件切换页面时是有默认过渡效果的但有时候设计师给的方案比较特殊默认的Tabs满足不了需求。这时候就得自己实现页面切换动画了。今天这个案例模拟了一个 Tab 页面切换效果——顶部有四个 Tab 标签点击不同的 Tab下方内容区域会有滑动 淡入的过渡效果。为什么不用原生 Tabs说实话原生Tabs组件能覆盖 80% 的场景。但它有几个局限切换动画的自定义程度有限不支持复杂的过渡组合比如滑动 淡入 缩放同时进行Tab 指示器的样式不够灵活当设计稿要求高度定制化的 Tab 切换效果时自己写一个反而更省心。核心实现状态定义EntryComponentstruct PageSwitchAnimation{StatecurrentPage:number0StateslideOffset:number0StatefadeIn:booleantrueprivatepages:string[][首页,消息,发现,我的]build(){Column(){// ...}}}三个状态变量各司其职currentPage当前选中的 Tab 索引slideOffset内容区域的水平偏移量fadeIn控制内容区域的透明度Tab 栏的实现Row(){ForEach(this.pages,(page:string,idx:number){Text(page).fontSize(14).fontColor(idxthis.currentPage?#4D96FF:#999999).fontWeight(idxthis.currentPage?FontWeight.Bold:FontWeight.Normal).layoutWeight(1).textAlign(TextAlign.Center).padding({top:8,bottom:8}).border({width:{bottom:idxthis.currentPage?2:0},color:#4D96FF}).onClick((){constdirectionidxthis.currentPage?1:-1this.slideOffsetdirection*100this.fadeInfalseanimateTo({duration:300,curve:Curve.EaseInOut},(){this.slideOffset0this.fadeIntruethis.currentPageidx})})})}.width(100%)Tab 栏的关键在于点击事件处理。来看这段逻辑constdirectionidxthis.currentPage?1:-1this.slideOffsetdirection*100this.fadeInfalseanimateTo({duration:300,curve:Curve.EaseInOut},(){this.slideOffset0this.fadeIntruethis.currentPageidx})先判断方向——如果点击的 Tab 在右边内容从右往左滑direction 1反之从左往右滑瞬间把内容偏移到起始位置不带动画同时设为透明在animateTo里把偏移量归零、透明度恢复同时更新当前页码内容区域Column(){Column().width(100%).height(160).backgroundColor(PRESET_COLORS[this.currentPage].value).borderRadius(16).opacity(this.fadeIn?1:0).translate({x:this.slideOffset}).animation({duration:350,curve:Curve.EaseInOut})Text(当前页面:${this.pages[this.currentPage]}).fontSize(18).fontWeight(FontWeight.Bold).margin({top:16})Text(页面切换支持滑动和淡入淡出过渡).fontSize(12).fontColor(#999999).margin({top:4})}内容区域同时绑定了opacity和translate实现滑动 淡入的组合效果。滑动方向的判断这是整个案例里最有意思的部分。用一个简单的比较就能确定滑动方向constdirectionidxthis.currentPage?1:-1操作directionslideOffset视觉效果点击右侧 Tab1100内容从右侧滑入点击左侧 Tab-1-100内容从左侧滑入点击当前 Tab不变0无动画这个逻辑模拟了原生Tabs的滑动方向判断但给了我们完全的控制权。优化建议加上手势滑动切换如果想更贴近原生体验可以给内容区域加上PanGesture根据滑动距离和速度判断切换方向。缓存页面内容当前方案每次切换都会重新渲染内容区域。如果页面内容比较重比如包含列表可以用visibility配合if来缓存页面。添加滑动指示器动画Tab 栏下方的指示线也可以做滑动动画让指示器跟着用户点击的位置平滑移动。写在最后自己实现页面切换动画核心就是两步判断方向 → 设置偏移量 →animateTo过渡。虽然比不上原生Tabs的丝滑但胜在灵活可控。如果你的项目里 Tab 切换效果有特殊要求不妨试试这个方案。代码量不大但能满足大部分定制化需求。