HarmonyOS 左滑TabContent内容切换时,Tabbar延时

用了Tabs组件,模拟器左滑改变了Tabcontent内容之后,Tabbar不及时更换,会延时几秒

HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Heiang

新增的onAnimationStart、onAnimationEnd和onGestureSwipe事件,本地测试不会感知到明显的延迟,demo如下:

import ComponentUtils from '@ohos.arkui.UIContext';

@Entry
@Component
export default struct Index {
  message: string = '通讯录'
  @State selectedFontColor: string = '#007DFF'
  @State fontColor: string = '#182431'
  @State currentPosition: number = 0
  // @Prop @Watch ('onRefresh') currentIndex: number
  private tabsController: TabsController = new TabsController()
  @State animationDuration: number = 300
  @State indicatorLeftMargin: number = 0
  @State indicatorWidth: number = 0
  @State currentIndex: number = 0
  private tabsWidth: number = 0
  private componentUtils: ComponentUtils.ComponentUtils = this.getUIContext().getComponentUtils()

  @Builder
  TabBuilder(index: number, name: ESObject) {
    Column() {
      Row() {
        Text(name)
          .fontColor(this.currentPosition === index ? this.selectedFontColor : this.fontColor)
          .fontSize(16)
          .fontWeight(this.currentPosition === index ? 600 : 400)
          .lineHeight(22)
          .margin({ top: 5, bottom: 5, left: 2 })
      }.width('95%').backgroundColor(this.currentPosition === index ? '#ffffff' : null).borderRadius(15)
    }.height('50%')
  }

  build() {
    Column() {

      Column() {
        Tabs({ barPosition: BarPosition.Start, index: this.currentPosition, controller: this.tabsController }) {
          TabContent() {
            Text('1111').fontSize(14)
          }.tabBar(this.TabBuilder(0, '最近联系人'))

          TabContent() {
            Text('2222').fontSize(14)
          }.tabBar(this.TabBuilder(1, '关注联系人'))

          TabContent() {
            Text('3333').fontSize(14)
          }.tabBar(this.TabBuilder(2, '我的群组'))

        }
        .vertical(false)
        .barMode(BarMode.Fixed)
        // .barWidth(360)
        .barHeight(65)
        .padding({ bottom: 15 })
        .onChange((index: number) => {
          this.currentPosition = index
        })
        .width('100%')
        .animationDuration(this.animationDuration)
        .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
          // 切换动画开始时触发该回调。下划线跟着页面一起滑动,同时宽度渐变。
          this.currentPosition = targetIndex
          let targetIndexInfo = this.getTextInfo(targetIndex)
          this.startAnimateTo(this.animationDuration, targetIndexInfo.left, targetIndexInfo.width)
        })
        .onAnimationEnd((index: number, event: TabsAnimationEvent) => {
          // 切换动画结束时触发该回调。下划线动画停止。
          let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event)
          this.startAnimateTo(0, currentIndicatorInfo.left, currentIndicatorInfo.width)
        })
        .onGestureSwipe((index: number, event: TabsAnimationEvent) => {
          // 在页面跟手滑动过程中,逐帧触发该回调。
          let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event)
          this.currentIndex = currentIndicatorInfo.index
          this.indicatorLeftMargin = currentIndicatorInfo.left
          this.indicatorWidth = currentIndicatorInfo.width
        })
      }
      .width('100%')
      .height('100%')
      .align(Alignment.TopStart)

      // .padding({top:20})
    }.width('100%').height('100%')
    .backgroundImageSize(ImageSize.Cover)
  }

  private getTextInfo(index: number): Record<string, number> {
    let rectangle = this.componentUtils.getRectangleById(index.toString())
    return { 'left': px2vp(rectangle.windowOffset.x), 'width': px2vp(rectangle.size.width) }
  }

  private getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> {
    let nextIndex = index
    if (index > 0 && event.currentOffset > 0) {
      nextIndex--
    } else if (index < 3 && event.currentOffset < 0) {
      nextIndex++
    }
    let indexInfo = this.getTextInfo(index)
    let nextIndexInfo = this.getTextInfo(nextIndex)
    let swipeRatio = Math.abs(event.currentOffset / this.tabsWidth)
    let currentIndex = swipeRatio > 0.5 ? nextIndex : index // 页面滑动超过一半,tabBar切换到下一页。
    let currentLeft = indexInfo.left + (nextIndexInfo.left - indexInfo.left) * swipeRatio
    let currentWidth = indexInfo.width + (nextIndexInfo.width - indexInfo.width) * swipeRatio
    return { 'index': currentIndex, 'left': currentLeft, 'width': currentWidth }
  }

  private startAnimateTo(duration: number, leftMargin: number, width: number) {
    animateTo({
      duration: duration, // 动画时长
      curve: Curve.Linear, // 动画曲线
      iterations: 1, // 播放次数
      playMode: PlayMode.Normal, // 动画模式
      onFinish: () => {
        console.info('play end')
      }
    }, () => {
      this.indicatorLeftMargin = leftMargin
      this.indicatorWidth = width
    })
  }
}

文档链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-container-tabs-V5#事件

分享
微博
QQ
微信
回复
2天前
相关问题
HarmonyOS 页面禁止
248浏览 • 1回复 待解决
HarmonyOStabbar显示
37浏览 • 1回复 待解决
HarmonyOS TabContent().tabBar 只能居中吗?
412浏览 • 1回复 待解决
HarmonyOS list 字体显示异常
55浏览 • 1回复 待解决
HarmonyOS 自定义tabbar对齐
36浏览 • 1回复 待解决
HarmonyOS tabs的tabBar怎么居
572浏览 • 1回复 待解决
【JS】如何实现删除功能?
3472浏览 • 1回复 待解决
获取返回手势方法
302浏览 • 1回复 待解决
HarmonyOS Tabs组件tabBar是否可以居
38浏览 • 1回复 待解决
HarmonyOS 二级页面关闭问题
295浏览 • 1回复 待解决
HarmonyOS TabContent内容如何手动刷新
21浏览 • 1回复 待解决