鸿蒙Next Scroll+List+Tabs实现关联滑动

2025-06-27 22:42:11
105次阅读
0个评论

实现一个Scroll嵌套List+Tabs,Tabs实现吸顶效果,Tabs标签可以随着List的滑动自动切换,切换Tabs标签时可以自动定位List位置。

实现思路:

1.滑动事件处理,Scroll嵌套List,向上滑动优先父容器滑动,向下滑动优先List滑动,滑动事件处理在绑定半模态页面那篇有介绍 2.Tabs吸顶,使用Column包裹Tabs+List,高度设置为屏幕高度,向上滑动时,Tabs就固定到顶部 3.Tabs和List关联滑动,需要监听Tabs的onChange事件,获取到点击Tab时的回调去控制List的滑动,监听List的onScrollIndex事件,获取到当前最上面的item的索引,根据业务需求去切换到指定的Tab

实现效果如下: 关联滑动.gif

@Entry
@Component
struct NestedScroll {
  @State arr: number[] = []
  @State selectedIndex: number = 0
  private controller: TabsController = new TabsController()
  private listScroller: ListScroller = new ListScroller()
  //样式封装,可以看一下我之前发的组件样式封装文章
  @Styles
  listCard() {
    .backgroundColor(Color.White)
    .height(72)
    .width("100%")
    .borderRadius(12)
  }
  //Tabs的简单使用可以查看之前的文章
  tabs: string[] = ['生活服务', '办公必备', '出行出差'];
  @Builder
  tabBuilder(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.selectedIndex === index ? '#007DFF' : '#182431')
        .fontSize(16)
        .fontWeight(this.selectedIndex === index ? 500 : 400)
        .lineHeight(22)
        .margin({ top: 17, bottom: 7 })
      Divider()
        .strokeWidth(2)
        .width(20)
        .margin({bottom:15})
        .color('#007DFF')
        .opacity(this.selectedIndex === index ? 1 : 0)
    }.width(81)
  }

  build() {
    Scroll() {
      Column() {
        Text("Scroll Area")
          .width("100%")
          .height("40%")
          .backgroundColor('#0080DC')
          .textAlign(TextAlign.Center)
        Column() {
          Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
            ForEach(this.tabs, (item: string, index: number) => {
              TabContent() {
              }.tabBar(this.tabBuilder(index, item))
            })
          }.height('auto')
          .onChange((index: number) => {
            // currentIndex控制TabContent显示页签
            this.selectedIndex = index
            if (index==0) {
              this.listScroller.scrollToIndex(0)
            }else if (index==1){
              this.listScroller.scrollToIndex(10)
            }else {
              this.listScroller.scrollToIndex(20)
            }
          })
          List({ space: 10 ,scroller:this.listScroller}) {
            ForEach(this.arr, (item: number) => {
              ListItem() {
                Text("item" + item)
                  .fontSize(16)
              }.listCard()
            }, (item: string) => item)
          }.width("100%")
          .edgeEffect(EdgeEffect.Spring)
          .nestedScroll({
            scrollForward: NestedScrollMode.PARENT_FIRST,
            scrollBackward: NestedScrollMode.SELF_FIRST
          })
          .onScrollIndex((start: number, end: number, center: number) => {
            if (start<10) {
              this.selectedIndex=0;
            }else if (start>=10&&start<20){
              this.selectedIndex=1;
            }else {
              this.selectedIndex=2;
            }
          })
        }.height('100%')

      }.width("100%")
    }
    .edgeEffect(EdgeEffect.Spring)
    .friction(0.6)
    .backgroundColor('#DCDCDC')
    .scrollBar(BarState.Off)
    .width('100%')
    .height('100%')
  }
  aboutToAppear() {
    for (let i = 0; i < 30; i++) {
      this.arr.push(i)
    }
  }
}
收藏00

登录 后评论。没有帐号? 注册 一个。