鸿蒙实现可以上下左右滑动的表格-摆脱大量ListScroller

鸿蒙实现可以上下左右滑动的表格-摆脱大量ListScroller

前言: 好久没写过文章了,最近在开发鸿蒙项目,于是乎想简单记录一下开发过程中遇到的一些好玩的东西或者经常会遇到的功能开发。

开发过程中经常遇到需要做可以上下左右滑动的类型的表格的实现,写之前也在华为论坛搜索了下相关的,官方文档提供了一种方案,创建了大量的ListScroller,个人感觉数据量大了就不是很好用,这里提供一种自己实现的方案

鉴于这个功能难度不是很大,仅仅就是布局和联动的实现,所以代码很少

效果

废话不多说,先上效果

由于CSDN上传gif失败,这里使用之前flutter 实现可以上下左右滑动的表格中的效果,和鸿蒙是一模一样的

布局

根据表格滑动的结构,可以看到布局结构如下,分别是横向滑动的标题,横向滑动的内容和上下滑动的标题+内容。

完整代码如下

ts 复制代码
@Entry
@ComponentV2
struct Index {
  leftWidth: number = 140
  cellWidth: number = 120
  cellHeight: number = 60
  titleHeight: number = 50
  private titleScroller: Scroller = new Scroller()
  private contentScroller: Scroller = new Scroller()
  private leftScroller: Scroller = new Scroller()
  private rightScroller: Scroller = new Scroller()
  titleList: string[] = []
  leftData: string[] = []
  rightData: string[] = []

  aboutToAppear(): void {
    for (let index = 0; index < 20; index++) {
      this.titleList.push(`标题${index}`)
    }
    for (let index = 0; index < 100; index++) {
      this.leftData.push(`左侧${index}`)
      this.rightData.push(`右侧行${index}`)
    }

  }

  build() {
    Column() {
      Row() {
        Text('标题').width(this.leftWidth).height(this.titleHeight).padding({ left: 16 })
        Scroll(this.titleScroller) {
          Row() {
            ForEach(this.titleList, (item: string) => {
              Text(item).width(this.cellWidth).height(this.titleHeight)
            })
          }
        }
        .layoutWeight(1)
        .scrollBar(BarState.Off)
        .edgeEffect(EdgeEffect.None)
        .scrollable(ScrollDirection.Horizontal)
        .onScrollFrameBegin((offset: number) => {
          this.contentScroller.scrollTo({
            xOffset: this.titleScroller.currentOffset().xOffset + offset,
            yOffset: 0,
            animation: false
          })
          return { offsetRemain: offset }
        })
      }.height(this.titleHeight)

      Column() {
        Row() {
          List({ scroller: this.leftScroller }) {
            Repeat<ESObject>(this.leftData).virtualScroll().each((ri: RepeatItem<ESObject>) => {
              ListItem() {
                Text(ri.item)
              }
              .height(this.cellHeight)
              .width(this.leftWidth)
              .itemBorder()
              .align(Alignment.Start)
              .padding({ left: 16 })
            })
            ListItem().height(this.cellHeight)
          }
          .width(this.leftWidth)
          .enableScrollInteraction(true)
          .scrollBar(BarState.Off)
          .edgeEffect(EdgeEffect.None)
          .cachedCount(20)
          .onScrollFrameBegin((offset: number) => {
            this.rightScroller.scrollTo({
              xOffset: 0,
              yOffset: this.leftScroller.currentOffset().yOffset + offset,
              animation: false
            })
            return ({ offsetRemain: offset })
          })

          Column() {
            Scroll(this.contentScroller) {
              List({ scroller: this.rightScroller }) {
                Repeat<string>(this.rightData).virtualScroll().each((ri: RepeatItem<ESObject>) => {
                  ListItem() {
                    Row() {
                      ForEach(this.titleList, (item: string, index: number) => {
                        Text(`${ri.item}列${index}`).width(this.cellWidth).height(this.cellHeight)
                      })
                    }
                  }.height(this.cellHeight).itemBorder()
                })
                ListItem().height(this.cellHeight)
              }
              .cachedCount(20)
              .enableScrollInteraction(true)
              .scrollBar(BarState.Off)
              .edgeEffect(EdgeEffect.None)
              .onScrollFrameBegin((offset: number) => {
                this.leftScroller.scrollTo({
                  xOffset: 0,
                  yOffset: this.rightScroller.currentOffset().yOffset + offset,
                  animation: false
                })
                return ({ offsetRemain: offset })
              })

            }
            .scrollBar(BarState.Off)
            .edgeEffect(EdgeEffect.None)
            .scrollable(ScrollDirection.Horizontal)
            .onScrollFrameBegin((offset: number) => {
              if (!this.contentScroller.isAtEnd()) {
                this.titleScroller.scrollTo({
                  xOffset: this.contentScroller.currentOffset().xOffset + offset,
                  yOffset: 0,
                  animation: false
                })
              }
              return { offsetRemain: offset }
            })
          }.layoutWeight(1)
        }
      }
    }
    .height('100%')
    .width('100%')
  }
}

@Styles
function itemBorder() {
  .border({
    color: '#cccccc',
    width: {
      left: 0,
      top: 0,
      right: 0,
      bottom: 1
    }
  })
}
相关推荐
奔跑的露西ly3 小时前
【HarmonyOS NEXT】Stage模型
华为·harmonyos
威哥爱编程4 小时前
鸿蒙 APP 还是卡顿?API 21 性能优化这 3 招,立竿见影!
harmonyos·arkts·arkui
威哥爱编程4 小时前
List 组件渲染慢?鸿蒙API 21 复用机制深度剖析,一行代码提速 200%!
harmonyos·arkts·arkui
以太浮标5 小时前
华为eNSP模拟器综合实验之- VLAN-QinQ技术解析
运维·网络·华为·信息与通信
2501_944521005 小时前
rn_for_openharmony商城项目app实战-语言设置实现
javascript·数据库·react native·react.js·harmonyos
程序猿追6 小时前
【鸿蒙PC桌面端开发】使用ArkTS做出RGB 色环选择器
华为·harmonyos
C雨后彩虹7 小时前
书籍叠放问题
java·数据结构·算法·华为·面试
zhujian826377 小时前
二十五、【鸿蒙 NEXT】@ObservedV2/@Trace实现组件动态刷新
华为·harmonyos·trace·lazyforeach·observedv2
wszy18098 小时前
rn_for_openharmony_空状态与加载状态:别让用户对着白屏发呆
android·javascript·react native·react.js·harmonyos
SameX8 小时前
鸿蒙应用的“任意门”:Deep Linking 与 App Linking 的相爱相杀
harmonyos