案例集合Tabs:自定义tabs左右边缘渐隐,切换动画衔接 + 更多按钮
·
🎯 案例集合Tabs:自定义tabs左右边缘渐隐,切换动画衔接 + 更多按钮
🌍 案例集合Tabs
🏷️ 效果图

📖 参考
🧩 拆解
-
自定义tabs(V1-V2组件都可用)使用fadingEdge Api 14
@Component export struct tabsMoreButAndFadingEdge { private mockData: string[] = ['购物', '体育', '财经', '服装', '军事', '政治', '居家', '国际', '科技', '城市', '景点'] private controller: TabsController = new TabsController() private listScroller: ListScroller = new ListScroller() @State selectIdx: number = 0 @State animationStartIdx: number = 0 @Builder tabBuilder(label: string, idx: number) { Text(label) .width(60) .height(40) .borderRadius('50%') .fontSize(16) .fontColor(this.animationStartIdx === idx ? Color.White : Color.Black) .backgroundColor(this.animationStartIdx === idx ? Color.Orange : '#80e0dede') .textAlign(TextAlign.Center) .onClick(() => { this.controller.changeIndex(idx) this.listScroller.scrollToIndex(idx, true, ScrollAlign.CENTER) this.selectIdx = this.animationStartIdx = idx }) } build() { Column() { Stack({ alignContent: Alignment.TopStart }) { Tabs({ index: this.selectIdx }) { ForEach(this.mockData, (item: string) => { TabContent() { Column() { Text(item) } .width('100%') .height('100%') .backgroundColor('#66e2dcdc') .justifyContent(FlexAlign.Start) } }) } .barHeight(0) .padding({ top: 50 }) // 关键:这里解决自定义tabs上面缺失的barHeight高度 .onChange((idx: number) => { this.selectIdx = idx }) // 关键:切换动画开始时触发该回调:解决切换tabs延迟的问题 .onAnimationStart((idx: number, targetIndex: number) => { if (idx === targetIndex) { return } this.listScroller.scrollToIndex(targetIndex, true, ScrollAlign.CENTER) this.animationStartIdx = targetIndex }) Row({ space: 10 }) { Row() { List({ scroller: this.listScroller, space: 10 }) { ForEach(this.mockData, (item: string, idx: number) => { this.tabBuilder(item, idx) }) } .width('100%') .height(40) .listDirection(Axis.Horizontal) .scrollBar(BarState.Off) .fadingEdge(true, { fadingEdgeLength: LengthMetrics.vp(40) }) } .height(40) .layoutWeight(1) Row() { Image($r('app.media.startIcon')) .width(20) .aspectRatio(1) } .width(40) .aspectRatio(1) .backgroundColor('#80e0dede') .borderRadius('50%') .justifyContent(FlexAlign.Center) .onClick(() => this.getUIContext().getPromptAction().showToast({ message: '周二周二浑浑噩噩' })) } .width('100%') .height(40) } } .width('100%') .height('100%') } } -
自定义tabs(V1-V2组件都可用)不使用fadingEdge 适合更低版本
@Component export struct tabsMoreButAndFadingEdge { private mockData: string[] = ['购物', '体育', '财经', '服装', '军事', '政治', '居家', '国际', '科技', '城市', '景点'] private controller: TabsController = new TabsController() private listScroller: ListScroller = new ListScroller() @State selectIdx: number = 0 @State animationStartIdx: number = 0 @State startFadingEdge: boolean = false @State endFadingEdge: boolean = false @Builder tabBuilder(label: string, idx: number) { Text(label) .width(60) .height(40) .borderRadius('50%') .fontSize(16) .fontColor(this.animationStartIdx === idx ? Color.White : Color.Black) .backgroundColor(this.animationStartIdx === idx ? Color.Orange : '#80e0dede') .textAlign(TextAlign.Center) .onClick(() => { this.controller.changeIndex(idx) this.listScroller.scrollToIndex(idx, true, ScrollAlign.CENTER) this.selectIdx = this.animationStartIdx = idx }) } build() { Column() { Stack({ alignContent: Alignment.TopStart }) { Tabs({ index: this.selectIdx }) { ForEach(this.mockData, (item: string) => { TabContent() { Column() { Text(item) } .width('100%') .height('100%') .backgroundColor('#66e2dcdc') .justifyContent(FlexAlign.Start) } }) } .barHeight(0) .padding({ top: 50 }) // 关键:这里解决自定义tabs上面缺失的barHeight高度 .onChange((idx: number) => { this.selectIdx = idx }) // 关键:切换动画开始时触发该回调:解决切换tabs延迟的问题 .onAnimationStart((idx: number, targetIndex: number) => { if (idx === targetIndex) { return } this.listScroller.scrollToIndex(targetIndex, true, ScrollAlign.CENTER) this.animationStartIdx = targetIndex }) Row({ space: 10 }) { Stack() { Row() { List({ scroller: this.listScroller, space: 10 }) { ForEach(this.mockData, (item: string, idx: number) => { this.tabBuilder(item, idx) }) } .width('100%') .height(40) .listDirection(Axis.Horizontal) .scrollBar(BarState.Off) .onScrollIndex(() => { this.startFadingEdge = true this.endFadingEdge = true }) .onReachStart(() => { this.startFadingEdge = false this.endFadingEdge = true }) .onReachEnd(() => { this.startFadingEdge = true this.endFadingEdge = false }) } Row() { Text() .width(60) .height(40) .linearGradient({ direction: GradientDirection.Left, colors: [['#00ffffff', 0.0], ['#ffffffff', 1.0]] }) .visibility(this.startFadingEdge ? Visibility.Visible : Visibility.Hidden) Blank() Text() .width(60) .height(40) .linearGradient({ direction: GradientDirection.Right, colors: [['#00ffffff', 0.0], ['#ffffffff', 1.0]] }) .visibility(this.endFadingEdge ? Visibility.Visible : Visibility.Hidden) } .width('100%') .height(40) .hitTestBehavior(HitTestMode.Transparent) // 关键:自身和子节点均响应触摸测试,不会阻塞兄弟节点和祖先节点的触摸测试 } .height(40) .layoutWeight(1) Row() { Image($r('app.media.startIcon')) .width(20) .aspectRatio(1) } .width(40) .aspectRatio(1) .backgroundColor('#80e0dede') .borderRadius('50%') .justifyContent(FlexAlign.Center) .onClick(() => this.getUIContext().getPromptAction().showToast({ message: '周二周二浑浑噩噩' })) } .width('100%') .height(40) } } .width('100%') .height('100%') } }
🌸🌼🌺
更多推荐



所有评论(0)