HarmonyOS 鸿蒙Next tab嵌套横向list实现自动滑动切换

发布于 1周前 作者 itying888 来自 鸿蒙OS

HarmonyOS 鸿蒙Next tab嵌套横向list实现自动滑动切换

tab嵌套横向list, tab的左右滑动 与横向list冲突。如何解决 

5 回复

可以参考以下代码实现list滑动到最右边就自动触发tab的滑动切换:

import { router } from '@kit.ArkUI'

@Entry

@Component

export struct Tabs240529160413047 {

  @State tabArray: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7]

  @State focusIndex: number = 0

  @State pre: number = 0

  @State index: number = 0

  private controller: TabsController = new TabsController()

  @State test: boolean = false

  @State animationDuration: number = 300

  @State indicatorLeftMargin: number = 0

  @State indicatorWidth: number = 0

  private tabWidth: number = 0;

  private scrollerForScroll: Scroller = new Scroller()

  // 单独的页签

  @Builder

  Tab(tabName: string, tabItem: number, tabIndex: number) {

    Row({ space: 20 }) {

      Text(tabName)

        .fontSize(18)

        .fontColor(tabIndex === this.focusIndex ? Color.Blue : Color.Black)

        .id(tabIndex.toString())

        .onAreaChange((oldValue: Area, newValue: Area) => {

          if (this.focusIndex === tabIndex && (this.indicatorLeftMargin === 0 || this.indicatorWidth === 0)) {

            if (newValue.position.x != undefined) {

              let positionX = Number.parseFloat(newValue.position.x.toString())

              this.indicatorLeftMargin = Number.isNaN(positionX) ? 0 : positionX

            }

            let width = Number.parseFloat(newValue.width.toString())

            this.tabWidth = Number.isNaN(width) ? 0 : width

            this.indicatorWidth = this.tabWidth

          }

        })

    }

    .justifyContent(FlexAlign.Center)

    .constraintSize({ minWidth: 35 })

    .width(120)

    .height(30)

    .onClick(() => {

      this.controller.changeIndex(tabIndex)

      this.focusIndex = tabIndex

    })

    .backgroundColor("#ffb7b7b7")

  }

  @Builder

  WebTab(tabName: string, tabItem: number, tabIndex: number) {

    Row({ space: 20 }) {

      Text(tabName).fontSize(18).fontColor(tabIndex === this.focusIndex ? Color.Blue : Color.Black)

    }

    .justifyContent(FlexAlign.Center)

    .constraintSize({ minWidth: 35 })

    .width(120)

    .height(30)

    .onClick(() => { 

      router.pushUrl({ url: ‘pages/WebPage’ })

    })

    .backgroundColor("#ffb7b7b7")

  }

  build() {

    Column() {

      Stack({ alignContent: Alignment.TopStart }) {

        Row() { // 页签

          List({ space: 0, initialIndex: 0, scroller: this.scrollerForScroll }) {

            ForEach(this.tabArray, (item: number, index: number) => {

              if (item == 4) {

                ListItem() {

                  this.WebTab("页签 " + item, item, index)

                }

              } else {

                ListItem() {

                  this.Tab("页签 " + item, item, index)

                }

              }

            }, (item: string) => item)

          }

          .listDirection(Axis.Horizontal)

          .height(30)

          .friction(0.6)

          .alignListItem(ListItemAlign.Start)

          .scrollBar(BarState.Off)

          .width(‘100%’)

          .backgroundColor("#ffb7b7b7")

          .onScroll((xOffset: number, yOffset: number) => {

            this.indicatorLeftMargin -= xOffset

          })

        }.width(‘100%’)

        Column()

          .height(2)

          .width(this.indicatorWidth)

          .margin({ left: this.indicatorLeftMargin, top: 30 })

          .backgroundColor(Color.Blue)

      }

      .height(40)

      .width(‘100%’)

      .backgroundColor("#ffb7b7b7") //tabs

      Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {

        ForEach(this.tabArray, (item: number, index: number) => {

          TabContent() {

            Text('我是页面 ’ + item + " 的内容").height(300).width(‘100%’).fontSize(30)

          }.backgroundColor(Color.White)

        }, (item: string) => item)

      }.width(‘100%’).barHeight(0).animationDuration(0).onChange((index: number) => {

        console.log(‘foo change’)

        this.focusIndex = index

        this.scrollerForScroll.scrollToIndex(index - 1, true)

        let indexInfo = this.getTextInfo(index)

        let currentLeft = indexInfo.left

        let currentWidth = indexInfo.width

        this.startAnimateTo(20, currentLeft, currentWidth)

      })

    }.width(‘100%’).height(‘100%’)

  }

  private getTextInfo(index: number): Record<string, number> {

    let strJson = getInspectorByKey(index.toString())

    try {

      let obj: Record<string, string> = JSON.parse(strJson)

      let rectInfo: number[][] = JSON.parse(’[’ + obj.$rect + ‘]’)

      return { ‘left’: px2vp(rectInfo[0][0]), ‘width’: px2vp(rectInfo[1][0] - rectInfo[0][0]) }

    } catch (error) {

      return { ‘left’: 0, ‘width’: 0 }

    }

  }

  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.tabWidth = width

      this.indicatorWidth = width

    })

  }

}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

更多关于HarmonyOS 鸿蒙Next tab嵌套横向list实现自动滑动切换的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


[@Entry](/user/Entry)
[@ComponentV2](/user/ComponentV2)
struct Index {
build() {
Tabs() {
TabContent() {
Column() {

}.size({ width: '100%', height: '100%' })
.backgroundColor(Color.Green)
}

TabContent() {
List() {
ListItem() {
Text('3').width('40%').backgroundColor(Color.Gray)
}

ListItem() {
Text('3').width('40%').backgroundColor(Color.Orange)
}

ListItem() {
Text('2').width('40%').backgroundColor(Color.Gray)
}

ListItem() {
Text('1').width('40%').backgroundColor(Color.Blue)
}
}.width('100%')
.listDirection(Axis.Horizontal)
.nestedScroll({
scrollForward: NestedScrollMode.SELF_FIRST,
scrollBackward: NestedScrollMode.SELF_FIRST,
})
}

TabContent() {
Column() {

}.size({ width: '100%', height: '100%' })
.backgroundColor(Color.Gray)
}
}.size({ width: '100%', height: '100%' })
}
}

list nestedScroll 嵌套滑动设定优先滑动自己。然后其余的系统会处理好

监听list滑动事件onScrollStop,通过控制器listscroller的isAtEnd判断是否滑动到底部,到底部时改变tab的选择角标

在HarmonyOS鸿蒙系统中实现Next tab嵌套横向list的自动滑动切换,可以通过以下方式实现:

  1. 布局设计:首先,确保你的布局文件中已经正确配置了Tab和横向List(例如,使用DirectionalLayoutStackLayout进行嵌套)。

  2. 数据绑定:将Tab和List的数据源进行绑定,确保每个Tab对应一个List。

  3. 自动滑动逻辑

    • 使用SwipeRefreshLayout或自定义滑动逻辑,通过定时器(如HandlerScheduledExecutorService)来控制List的自动滑动。
    • 监听Tab的切换事件,根据当前Tab调整滑动的List。
  4. 动画效果:为滑动添加动画效果,以提升用户体验。可以使用AnimatorAnimation类来实现平滑过渡。

  5. 事件处理:处理用户手动滑动和自动滑动之间的冲突,确保用户体验流畅。

  6. 生命周期管理:在Activity或Ability的生命周期中,合理管理定时器和滑动逻辑,避免内存泄漏或不必要的资源消耗。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。确保提供详细的错误信息和代码示例,以便客服人员更快地定位并解决问题。

回到顶部