【HarmonyOS】自定义TabLayout示例
【HarmonyOS】自定义TabLayout代码示例,通过 Scroll 锚点 Tab 布局,滚动条会自动滚动使选中的标签居中显示。
class MyTabItem { label: string = ""; positionX: number = -1; // 当前位置 width: number = -1; // 当前宽度 constructor(label: string) { this.label = label; } } @Component struct MyTabLayout { onSelected?: (selectedIndex: number) => void; scroller: Scroller = new Scroller(); @Prop tabItems: MyTabItem[]; @State @Watch('selectIndexChanged') selectedIndex: number = 0; @State tabBarWidth: number = 0; // Tab 栏宽度 selectIndexChanged() { if (this.onSelected) { this.onSelected(this.selectedIndex); } } build() { Column() { Scroll(this.scroller) { Row() { ForEach(this.tabItems, (item: MyTabItem, index: number) => { Row() { Image($r('app.media.app_icon')).width('44lpx').height('44lpx'); Text(item.label) .margin({ left: '16lpx' }) .fontColor(index === this.selectedIndex ? "#FF1919" : "#2E2E2E") .fontSize('30lpx'); }.padding({ right: '16lpx' }) .onAreaChange((previousArea: Area, currentArea: Area) => { if (item.positionX === -1) { item.positionX = currentArea.position.x as number; } if (item.width === -1) { item.width = currentArea.width as number; } }) .onClick(() => { this.selectedIndex = index; this.scroller.scrollTo({ xOffset: (item.positionX - this.tabBarWidth / 2 + item.width / 2), yOffset: 0, animation: true }); }); }); }.height('95lpx'); } .scrollable(ScrollDirection.Horizontal) .scrollBar(BarState.Off) .borderWidth({ bottom: 1 }) .borderColor("#e3e3e3") .align(Alignment.Start) .width('100%') .onAreaChange((previousArea: Area, currentArea: Area) => { this.tabBarWidth = currentArea.width as number; }); } } } @Entry @Component struct Page11 { scroller: Scroller = new Scroller(); @State tabItems: MyTabItem[] = []; @State selectedIndex: number = 0 getRandomInt(min: number, max: number): number { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; } aboutToAppear(): void { for (let i = 0; i < 20; i++) { this.tabItems.push(new MyTabItem(`项目:${this.getRandomInt(1, 10000)}`)); } } build() { Column() { MyTabLayout({ tabItems: this.tabItems, onSelected: (selectedIndex: number) => { console.info(`当前选择的位置: ${selectedIndex}`); this.selectedIndex = selectedIndex } }); Stack() { Text(`当前选择的位置:${this.selectedIndex}`) }.width('100%') .layoutWeight(1) .backgroundColor(Color.Orange) } .height('100%') .width('100%'); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了