HarmonyOS鸿蒙Next中如何解决tabs嵌套支持二级分类滑动到最后一个时切换一级分类title到下一个位置的问题

HarmonyOS鸿蒙Next中如何解决tabs嵌套支持二级分类滑动到最后一个时切换一级分类title到下一个位置的问题 在使用Tabs的时候,出现一级标题有多个,然后一级标题的内容下面还有tabs的分类,当二级分类滑动到了最后一个的时候,如何切换到一级分类的下一个:

比如:

  • 一级分类: 可用美团平台劵,可用淘宝商家劵,返现
  • 二级分类: 全部,商城劵,上海劵,天津劵,线下消费劵

使用情况: 当处于一级分类:可用美团平台劵的时候,二级分类进行向左滑动到最后一个的时候,再向左滑动,需要切换到一级分类的:可用淘宝商家劵,然后当一级分类处于:可以淘宝商家劵的时候,下面的二级分类,如何滑动到第一个的时候,再次向左滑动希望可以切换到第一分类的:可以美团平台劵,在最后一个的时候向右滑动,希望可以切换一级分类到下一个:返现这里

现象: 现在是不能支持这样滑动效果的
期望: 可以支持这种嵌套类型的,左右滑动,切换一级,二级内容


更多关于HarmonyOS鸿蒙Next中如何解决tabs嵌套支持二级分类滑动到最后一个时切换一级分类title到下一个位置的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

请参考以下代码:

@Entry
@Component

struct NestedCeiling {

  private listArr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

  private scrollerForScroll: Scroller = new Scroller();

  private scrollerForList: Scroller = new Scroller();

  @State currentIndexTop:number = 0;//上层tabs索引

  @State currentIndexUnder:number = 0;//下层tabs索引

  @Builder
  tabBuilder(index: number, name: string) {
    Column () {
      Text(name)
        .fontSize($r('app.float.middle_font_size'))
        .lineHeight($r('app.float.title_line_height'))
        .margin({
          top: $r('app.float.title_margin_top'),
          bottom: $r('app.float.title_margin_bottom')
        })
    }
  }

  @Builder
  listBuilder(listName: string, index: number) {
    Column () {
      Text(listName)
        .fontColor(this.currentIndexTop == index?'#007DFF':Color.Gray)
        .onClick(()=>{
          this.currentIndexTop = index
          this.currentIndexUnder = 0
        })
      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.currentIndexTop === index ? 1 : 0)
    }.width('100%')
  }

  //第四个参数,自主标记是否为最后一个
  @Builder
  listBuilder2(listName: string, index: number){
    //todo 2、判断为最后一个TabContent时增加拖拽事件
    if(index == 4){
      TabContent () {
        List({ space: 10, scroller: this.scrollerForList }) {
          ForEach(this.listArr, (item: number) => {
            ListItem () {
              Text(listName + item)
                .width('100%')
                .height('100%')
                .borderRadius($r('app.float.list_item_radius'))
                .fontSize($r('app.float.middle_font_size'))
                .fontWeight(500)
                .padding({ left: $r('app.float.list_item_padding') })
                .backgroundColor(Color.White)
            }
          }, (item: string) => JSON.stringify(item))
        }
        .padding({
          left: $r('app.float.list_padding'),
          right: $r('app.float.list_padding')
        })
        .width('100%')
        .height('100%')
        .edgeEffect(EdgeEffect.None)
        .scrollBar(BarState.Off)
        .nestedScroll({
          scrollForward: NestedScrollMode.PARENT_FIRST,
          scrollBackward: NestedScrollMode.SELF_FIRST
        })
      }
      //todo 3、绑定手势动作
      .gesture(
        // 绑定拖动手势,向右,移动距离为5vp(默认)时触发
        PanGesture({direction:PanDirection.Left})
          .onActionStart(() => {
            if (this.currentIndexTop == 2) {
              this.currentIndexTop = 0
            } else {
              this.currentIndexTop++
            }
            this.currentIndexUnder=0
          })
      )
      .tabBar(SubTabBarStyle.of(listName+""))
    }

    //todo 2、判断为第一个TabContent时增加拖拽事件
    else if(index == 0){
      TabContent () {
        List({ space: 10, scroller: this.scrollerForList }) {
          ForEach(this.listArr, (item: number) => {
            ListItem () {
              Text(listName + item)
                .width('100%')
                .height('100%')
                .borderRadius($r('app.float.list_item_radius'))
                .fontSize($r('app.float.middle_font_size'))
                .fontWeight(500)
                .padding({ left: $r('app.float.list_item_padding') })
                .backgroundColor(Color.White)
            }
          }, (item: string) => JSON.stringify(item))
        }
        .padding({
          left: $r('app.float.list_padding'),
          right: $r('app.float.list_padding')
        })
        .width('100%')
        .height('100%')
        .edgeEffect(EdgeEffect.None)
        .scrollBar(BarState.Off)
        .nestedScroll({
          scrollForward: NestedScrollMode.PARENT_FIRST,
          scrollBackward: NestedScrollMode.SELF_FIRST
        })
      }
      //todo 3、绑定手势动作
      .gesture(
        // 绑定拖动手势,向右,移动距离为5vp(默认)时触发
        PanGesture({direction:PanDirection.Right})
          .onActionStart(() => {
            if (this.currentIndexTop == 0) {
              this.currentIndexTop = 2
            } else {
              this.currentIndexTop--
            }
            this.currentIndexUnder=0
          })
      )
      .tabBar(SubTabBarStyle.of(listName+""))
    }

    else{
      TabContent () {
        List({ space: 10, scroller: this.scrollerForList }) {
          ForEach(this.listArr, (item: number) => {
            ListItem () {
              Text(listName + item)
                .width('100%')
                .height('100%')
                .borderRadius($r('app.float.list_item_radius'))
                .fontSize($r('app.float.middle_font_size'))
                .fontWeight(500)
                .padding({ left: $r('app.float.list_item_padding') })
                .backgroundColor(Color.White)
            }
          }, (item: string) => JSON.stringify(item))
        }
      }
      .tabBar(SubTabBarStyle.of(listName+""))
    }
  }

  build() {
    Column () {
      Scroll(this.scrollerForScroll) {
        Column () {
          Flex({direction:FlexDirection.Row,justifyContent:FlexAlign.Center}){
            this.listBuilder('可用美团平台劵', 0)
            this.listBuilder('可用淘宝商家劵', 1)
            this.listBuilder('返现', 2)
          }
          Tabs({index:$$this.currentIndexUnder}) {
            this.listBuilder2('全部', 0)
            this.listBuilder2('商城劵', 1)
            this.listBuilder2('上海劵', 2)
            this.listBuilder2('天津劵', 3)
            this.listBuilder2('线下消费劵', 4)
          }
        }
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.start_window_background'))
  }
}

更多关于HarmonyOS鸿蒙Next中如何解决tabs嵌套支持二级分类滑动到最后一个时切换一级分类title到下一个位置的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,解决tabs嵌套支持二级分类滑动到最后一个时切换一级分类title到下一个位置的问题,可以通过监听滑动事件和动态更新一级分类的title来实现。具体步骤如下:

  1. 监听滑动事件:使用OnPageChangeListenerOnTabSelectedListener来监听二级分类的滑动事件,当滑动到最后一个二级分类时触发回调。

  2. 动态更新一级分类的title:在滑动到最后一个二级分类时,通过代码动态更新一级分类的title,切换到下一个一级分类的title。

  3. 联动一级分类切换:在更新一级分类的title后,联动一级分类的切换,确保UI和逻辑的一致性。

例如,使用TabLayoutViewPager实现时,可以在OnPageChangeListeneronPageSelected方法中判断当前是否是最后一个二级分类,如果是,则调用TabLayoutselectTab方法切换到下一个一级分类。

// 伪代码示例
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        if (position == lastSecondaryTabPosition) {
            tabLayout.selectTab(tabLayout.getTabAt(nextPrimaryTabIndex));
        }
    }
});

在HarmonyOS鸿蒙Next中,解决tabs嵌套二级分类滑动到最后一个时切换一级分类title到下一个位置的问题,可以通过监听二级分类的滑动事件,判断是否滑动到最后一个item。如果是,则手动调用一级分类的切换方法,更新一级分类的title到下一个位置。具体实现如下:

// 监听二级分类的滑动事件
tabComponent.setOnPageChangeListener(new TabComponent.OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        // 判断是否滑动到最后一个item
        if (position == tabComponent.getTabCount() - 1) {
            // 获取当前一级分类的位置
            int currentPrimaryTab = primaryTabComponent.getSelectedTabPosition();
            // 切换到下一个一级分类
            primaryTabComponent.selectTab(currentPrimaryTab + 1);
            // 更新一级分类的title
            primaryTabComponent.updateTabTitle(currentPrimaryTab + 1, "新标题");
        }
    }
});

通过这种方式,可以在二级分类滑动到最后一个时,自动切换一级分类的title到下一个位置。

回到顶部