HarmonyOS鸿蒙Next中如何解决自定义tabBar切换动画有明显延迟感的问题

HarmonyOS鸿蒙Next中如何解决自定义tabBar切换动画有明显延迟感的问题

【问题现象】

Tabs页面切换时,tabBar切换动画发生的比较慢,需要等到Tabs页面完成切换时,tabBar才发生切换。如下图所示,从blue页签切换到yellow页签,页面都基本切换完成了,但是页签还没有发生切换。

点击放大

【背景知识】

  • 组件

Tabs组件:通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。

  • 事件

onChange:Tab页签切换后触发的事件。

onAnimationStart:切换动画开始时触发该回调。

【定位思路】

因为问题出在了tabBar切换速度比较慢,可以猜测是currentIndex发生变化的时机不正确。查看代码发现是在onchange的时候才改变currentIndex,所以导致tabBar切换得比较慢。

Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
  // 省略tabContent内容
}
.vertical(false)
.barMode(BarMode.Fixed)
.animationDuration(400)
.onChange((index: number) => {
  // currentIndex控制TabContent显示页签
  this.currentIndex = index
})

【解决方案】

新增一个selectedIndex的索引用于标识被选择的tabBar,原来的currentIndex仍然用于TabContent页签显示的控制。然后selectedIndex在onAnimationStart事件中进行切换,就可以实现页签内容切换动画发生时,tabBar也同步切换。需要注意的是,selectedIndex和currentIndex不能为了方便使用同一个,否则会出现页面切换没有动画的情况。

@Entry
@Component
struct Index {
  // ......

  @Builder
  tabBuilder(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
        .fontSize(16)
        .fontWeight(this.selectedIndex === index ? 500 : 400)
        .lineHeight(22)

      Divider()
        .strokeWidth(2)
        .color('# 007DFF')
        .opacity(this.selectedIndex === index ? 1 : 0)
    }.width('100%')
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
        // 省略tabContent内容
      }
      // ......
      .onChange((index: number) => {
        // currentIndex控制TabContent显示页签
        this.currentIndex = index
      })
      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
        if (index === targetIndex) {
          return
        }
        // selectedIndex控制自定义TabBar内Image和Text颜色切换
        this.selectedIndex = targetIndex;
      })
    }.width('100%')
  }
}

修改后,可以看到,页签内容切换动画发生时,tabBar也立即发生了变化。

点击放大

【总结】

想要使得Tabs滑动切换动画发生的时候,tabBar也同步进行切换,需要在onAnimationStart事件中进行索引更新,而且标识选中tabBar的索引要和标识选中tab页的索引区分开。


更多关于HarmonyOS鸿蒙Next中如何解决自定义tabBar切换动画有明显延迟感的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中如何解决自定义tabBar切换动画有明显延迟感的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,自定义tabBar切换动画有明显延迟感的问题可以通过以下步骤解决:

  1. 新增一个selectedIndex用于标识被选择的tabBar,保持currentIndex用于TabContent页签显示的控制。
  2. onAnimationStart事件中更新selectedIndex,确保tabBar在动画开始时同步切换。
  3. 确保selectedIndexcurrentIndex不共用同一个变量,以避免页面切换无动画的问题。

修改后的代码示例如下:

@Entry
@Component
struct Index {
  @State currentIndex: number = 0;
  @State selectedIndex: number = 0;

  @Builder
  tabBuilder(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.selectedIndex === index ? '#007DFF' : '#000000')
        .fontSize(16)
        .fontWeight(this.selectedIndex === index ? 500 : 400)
        .lineHeight(22)

      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.selectedIndex === index ? 1 : 0)
    }.width('100%')
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
        // 省略tabContent内容
      }
      .onChange((index: number) => {
        this.currentIndex = index;
      })
      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
        if (index === targetIndex) {
          return;
        }
        this.selectedIndex = targetIndex;
      })
    }.width('100%')
  }
}

通过此修改,tabBar会在页面切换动画开始时同步切换,消除延迟感。

回到顶部