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

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

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

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

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

效果

废话不多说,先上效果

布局

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

完整代码如下

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
    }
  })
}
相关推荐
bugcome_com2 小时前
JWT 知识小课堂:从入门到精通,一文吃透 JSON Web Token
前端·json
To_OC2 小时前
写了三天 Next.js,我的 React 世界观被拆了又装回去
前端·全栈·next.js
独泪了无痕3 小时前
viewer.js 安装与配置指南:实现图片预览功能
前端·vue.js
梦想不只是梦与想5 小时前
鸿蒙应用api的兼容性:参数配置(二)
harmonyos·sdk版本·sdkversion
Fluxart.ai5 小时前
电商商品图审核怎么自动化?规则引擎、人工复核与发布门禁
java·前端·自动化
why技术5 小时前
AI 写的文章,可能都带着手敲一遍都去不掉的“隐形水印”。
前端·人工智能·后端
愚公搬代码5 小时前
【愚公系列】《Android应用案例开发大全》016-LBS类应用掌上杭州(辅助工具类的开发)
android·前端
CodeSheep5 小时前
又一个华为天才少年,离职了!
前端·后端·程序员
kyriewen6 小时前
面试官说"打开你的AI工具"——我才发现,他考的根本不是写代码
前端·人工智能·面试
IT_陈寒7 小时前
Vue的双向绑定把我坑惨了,原来这个场景不能用
前端·人工智能·后端