参考下此demo:const listArr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; export class CommonConstants { static readonly TAB_NAME_1: string = 'Tab1'; static readonly TAB_NAME_2: string = 'Tab2'; static readonly LIST_NAME_1: string = 'Tab1_List'; static readonly LIST_NAME_2: string = 'Tab2_List'; static readonly FONT_WEIGHT_FIVE: number = 500; static readonly FONT_WEIGHT_FOUR: number = 400; static readonly STROKE_WIDTH: number = 2; static readonly LIST_SPACE: number = 12; static readonly STACK_HEIGHT: Length = "calc(100% - 60vp)"; static readonly FULL_OPACITY: number = 1; static readonly ZERO_OPACITY: number = 0; static readonly FULL_WIDTH: string = '100%'; static readonly FULL_HEIGHT: string = '100%'; } @Entry @Component struct TabDemo { @State currentIndex: number = 0; private scrollerForScroll: Scroller = new Scroller(); private scrollerForList: Scroller = new Scroller(); @State isRefreshing: boolean = false private currentOffsetY: number = 0; private controller: TabsController = new TabsController() @State tabArray: Array<string> = [CommonConstants.TAB_NAME_1,CommonConstants.TAB_NAME_2 ] @Builder tabBuilder(index: number, name: string) { Column() { Text(name) .fontColor(this.currentIndex === index ? $r('app.color.start_window_background') : $r('app.color.start_window_background')) .fontSize('14fp') .fontWeight(this.currentIndex === index ? CommonConstants.FONT_WEIGHT_FIVE : CommonConstants.FONT_WEIGHT_FOUR) Divider() .strokeWidth(CommonConstants.STROKE_WIDTH) .opacity(this.currentIndex === index ? CommonConstants.FULL_OPACITY : CommonConstants.ZERO_OPACITY) } } // 单独的页签 @Builder Tab(tabName: string, tabItem: number, tabIndex: number) { Column({ space: 20 }) { Text(tabName) .fontSize(22) .fontColor(tabIndex === this.currentIndex ? "#0000FF " : "#000000") .margin({top: '17%'}) } .onClick(() => { console.log(tabIndex+''); this.controller.changeIndex(tabIndex) this.currentIndex = tabIndex }) .width(85) .height(60) } @Builder listBuilder(listName: string, tabName: string, index: number) { TabContent() { List({ space: CommonConstants.LIST_SPACE, scroller: this.scrollerForList }) { ForEach(listArr, (item: number) => { ListItem() { Text(listName + item) .width(CommonConstants.FULL_WIDTH) .height(CommonConstants.FULL_HEIGHT) .fontWeight(CommonConstants.FONT_WEIGHT_FIVE) .backgroundColor(Color.White) } .width(CommonConstants.FULL_WIDTH) }, (item: string) => JSON.stringify(item)) } .width(CommonConstants.FULL_WIDTH) .height(CommonConstants.FULL_HEIGHT) .edgeEffect(EdgeEffect.None) .scrollBar(BarState.Off) .nestedScroll({ scrollForward: NestedScrollMode.PARENT_FIRST, scrollBackward: NestedScrollMode.SELF_FIRST }) } // .tabBar(this.tabBuilder(index, tabName)) } build() { Column() { Text('tsh') .fontWeight(FontWeight.Bold) .textAlign(TextAlign.Start) .width(CommonConstants.FULL_WIDTH) Stack({ alignContent: Alignment.Top }) { Scroll(this.scrollerForScroll) { Column() { Image($r("app.media.app_icon")) .width(CommonConstants.FULL_WIDTH) // Refresh({ refreshing: $$this.isRefreshing,promptText:'正在刷新'}){ Stack({ alignContent: Alignment.Top }){ Column(){ Text('加载中......').visibility(this.isRefreshing? Visibility.Visible : Visibility.Hidden) Tabs({ barPosition: BarPosition.Start, controller: this.controller }) { this.listBuilder(CommonConstants.LIST_NAME_1, CommonConstants.TAB_NAME_1, 0) this.listBuilder(CommonConstants.LIST_NAME_2, CommonConstants.TAB_NAME_2, 1) } // .barPosition(BarPosition.Start) // .vertical(true) .barHeight(0) .onChange((index: number) => { this.currentIndex = index; }) .onTabBarClick((index) =>{ this.currentIndex = index }) } .padding({top:80}) Row({ space: 7 }) { Scroll() { Row() { ForEach(this.tabArray, (item: string, index: number) => { this.Tab(item,index,index) }) } } .align(Alignment.Start) .scrollable(ScrollDirection.Horizontal) .scrollBar(BarState.Off) .width('100%') .height('10%') .backgroundColor(Color.Pink) } .width('100%') .backgroundColor(Color.Pink) } // } // .onRefreshing(() => { // setTimeout(() => { // this.isRefreshing = false // }, 2000) // console.log('onRefreshing test') // }) } .onTouch((event?: TouchEvent) => { if (event === undefined) { return; } switch (event.type) { case TouchType.Down: this.currentOffsetY = event.touches[0].y; break; case TouchType.Move: let isDownPull = event.touches[0].y - this.currentOffsetY > 50; if (isDownPull && this.scrollerForScroll.currentOffset().yOffset === 0) { this.isRefreshing = true; setTimeout(()=>{ this.isRefreshing = false; },1500) console.log(event.touches[0].y.toString(),isDownPull) console.log('下拉中') } } }) } .scrollBar(BarState.Off) .width(CommonConstants.FULL_WIDTH) .height(CommonConstants.FULL_HEIGHT) } .width(CommonConstants.FULL_WIDTH) .height(CommonConstants.STACK_HEIGHT) } .height(CommonConstants.FULL_HEIGHT) .backgroundColor($r('app.color.start_window_background')) } }
参考下此demo: