鸿蒙实现可以上下左右滑动的表格-摆脱大量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
    }
  })
}
相关推荐
国服第二切图仔4 小时前
Electron for 鸿蒙PC项目实战之拖拽组件示例
javascript·electron·harmonyos
国服第二切图仔4 小时前
Electron for鸿蒙PC项目实战之天气预报应用
javascript·electron·harmonyos·鸿蒙pc
国服第二切图仔5 小时前
Electron for鸿蒙PC项目之侧边栏组件示例
javascript·electron·harmonyos·鸿蒙pc
RisunJan5 小时前
HarmonyOS 系统概述
华为·harmonyos
泓博5 小时前
鸿蒙网络请求流式返回实现方法
华为·harmonyos
国服第二切图仔6 小时前
Electron for鸿蒙pc项目实战之下拉菜单组件
javascript·electron·harmonyos·鸿蒙pc
汉堡黄•᷄ࡇ•᷅7 小时前
鸿蒙开发:案例集合List:多级列表(商品分类)
harmonyos·鸿蒙·鸿蒙系统
北方的流星8 小时前
华为AC+AP旁挂式三层无线局域网的配置案例
运维·网络·经验分享·华为
国服第二切图仔8 小时前
Electron for 鸿蒙PC项目开发之模态框组件
javascript·electron·harmonyos