HarmonyOS鸿蒙Next中Scroll嵌套List时滑动到底部添加数据内容区域未变化问题

HarmonyOS鸿蒙Next中Scroll嵌套List时滑动到底部添加数据内容区域未变化问题

示例4嵌套滚动父组件向子组件传递滚动

图一 图二

Scroll嵌套List,当Scroll滑动到底部,这时候点击按钮向list添加了10条数据,但是Scroll的内容区没有发生改变还是图一的效果,但是我想要的是添加完数据后得到图二的效果。

@Entry
@Component
struct NestedScroll {
  private headerHeight: number = 0;
  @State arr: number[] = [];
  private scrollerForParent: Scroller = new Scroller();
  private scrollerForChild: Scroller = new Scroller();

  aboutToAppear(): void {
    this.arr = this.getData(0, 10)
  }

  getData(start: number, count: number): Array<number> {
    const arr: Array<number> = []
    for (let i = 0; i < count; i++) {
      arr.push(i + start)
    }
    return arr
  }

  build() {
    Column() {
      Button('添加数据')
        .onClick(() => {
          const items = this.getData(this.arr.length, 10)
          this.arr.push(...items)
        })
      Scroll(this.scrollerForParent) {
        Column() {
          Text("header")
            .width("100%")
            .height("40%")
            .backgroundColor(0X330000FF)
            .fontSize(16)
            .textAlign(TextAlign.Center)
            .onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) => {
              this.headerHeight = newValue.height! as number;
            })
          List({ space: 20, scroller: this.scrollerForChild }) {
            ForEach(this.arr, (item: number) => {
              ListItem() {
                Text("ListItem" + item)
                  .width("100%")
                  .height("100%")
                  .borderRadius(15)
                  .fontSize(16)
                  .textAlign(TextAlign.Center)
                  .backgroundColor(Color.White)
              }.width("100%").height(100)
            }, (item: string) => item)
          }
          .width("100%")
          .height("100%")
          .edgeEffect(EdgeEffect.None)
          .scrollBar(BarState.Off)
          .enableScrollInteraction(false)

          Text("已经滑动到底部了")
            .width("100%")
            .height("10%")
            .backgroundColor(0X330000FF)
            .fontSize(16)
            .textAlign(TextAlign.Center)

        }
      }
      .scrollBar(BarState.Off)
      .edgeEffect(EdgeEffect.Spring)
      .onScrollFrameBegin((offset: number, state: ScrollState) => {
        let retOffset = offset;
        let currOffset = this.scrollerForParent.currentOffset().yOffset;
        let newOffset = currOffset + offset;
        if (offset > 0) {
          if (this.scrollerForChild.isAtEnd()) {
            return { offsetRemain: offset };
          }
          if (newOffset > this.headerHeight) {
            retOffset = this.headerHeight - currOffset;
          }
          this.scrollerForChild.scrollBy(0, offset - retOffset);
        } else {
          if (this.scrollerForChild.currentOffset().yOffset <= 0) {
            return { offsetRemain: offset };
          }
          if (newOffset < this.headerHeight) {
            retOffset = this.headerHeight - currOffset;
          }
          this.scrollerForChild.scrollBy(0, offset - retOffset);
        }
        return { offsetRemain: retOffset };
      })
      .width("100%")
      .layoutWeight(1)
      .backgroundColor(0xDCDCDC)
    }
    .width("100%")
    .height("100%")
  }
}

更多关于HarmonyOS鸿蒙Next中Scroll嵌套List时滑动到底部添加数据内容区域未变化问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复

Scroll组件嵌套List组件,并且在Scroll滑动到底部时向List添加数据,通常会导致Scroll的内容区域发生变化。因为添加数据后,List的高度会增加,从而影响到外层Scroll的滚动行为。

使用nestedScroll属性:可以试试在List组件上设置nestedScroll属性,这样List内部的滚动事件就不会与外层Scroll冲突。例:

@Component
export struct ScrollNestingList {
    build() {
        Scroll() {
            Column() {
                Text('This is the title')
                    .fontSize(50)
                    .fontWeight(FontWeight.Bold)
                List() {
                    ForEach(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'], (item: string) => {
                        ListItem() {
                            Text(item)
                                .fontSize(50)
                                .height(150)
                        }
                    }, (item: string) => item)
                }
                .nestedScroll({})
            }
        }
    }
}

这样设置后,List的滚动不会影响到外层Scroll的滚动行为,从而解决在滑动到底部并添加数据时遇到的问题。

监听Scroll的滚动事件:也可以通过监听Scroll的滚动事件来动态调整内容区域。当检测到Scroll已滑动到底部时,程序可以自动添加数据到List中,同时更新Scroll的高度以适应新的内容。

更多关于HarmonyOS鸿蒙Next中Scroll嵌套List时滑动到底部添加数据内容区域未变化问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


补充说明一下,点击按钮添加数据后内容区没变,然后再向下滑动它就正常了

7963e-32766.gif

可以试一下滚动事件,添加以后 触发向上滚动,

可以检查一下Foreach键值生成规则,在ForEach组件进行非首次渲染时,它会检查新生成的键值是否在上次渲染中已经存在。如果键值不存在,则会创建一个新的组件;如果键值存在,则不会创建新的组件,而是直接渲染该键值所对应的组件。如果键值生成规则不一致,会导致不渲染的情况ForEach:循环渲染-学习UI范式渲染控制-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

ForEach(this.arr, (item: number) => { ListItem() { Text(“ListItem” + item) .width(“100%”) .height(“100%”) .borderRadius(15) .fontSize(16) .textAlign(TextAlign.Center) .backgroundColor(Color.White) }.width(“100%”).height(100) }, (item: number, index: number) => item.toString())

没注意,我改了一下keyGenerator,但是效果还是一样的,初始化的key是’0’到’9’,点击添加的数据是’10’到’19’,

@Entry @Component struct TestPage { private headerHeight: number = 0; @State arr: number[] = []; private scrollerForParent: Scroller = new Scroller(); private scrollerForChild: Scroller = new Scroller();

aboutToAppear(): void { this.arr = this.getData(0, 10) }

getData(start: number, count: number): Array<number> { const arr: Array<number> = [] for (let i = 0; i < count; i++) { arr.push(i + start) } return arr }

build() { Column() { Button(‘添加数据’) .onClick(() => { const items = this.getData(this.arr.length, 10) this.arr.push(…items) }) Scroll(this.scrollerForParent) { Column() { Text(“header”) .width(“100%”) .height(“40%”) .backgroundColor(0X330000FF) .fontSize(16) .textAlign(TextAlign.Center) .onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) => { this.headerHeight = newValue.height! as number; }) List({ space: 20, scroller: this.scrollerForChild }) { ForEach(this.arr, (item: number) => { ListItem() { Text(“ListItem” + item) .width(“100%”) .height(“100%”) .borderRadius(15) .fontSize(16) .textAlign(TextAlign.Center) .backgroundColor(Color.White) }.width(“100%”).height(100) }, (item: string) => item)

        ListItem() {
          Text("已经滑动到底部了")
            .width("100%")
            .height("10%")
            .backgroundColor(0X330000FF)
            .fontSize(16)
            .textAlign(TextAlign.Center)
        }

      }
      .width("100%")
      .height("100%")
      .edgeEffect(EdgeEffect.None)
      .scrollBar(BarState.Off)
      .enableScrollInteraction(false)

    }
  }
  .scrollBar(BarState.Off)
  .edgeEffect(EdgeEffect.Spring)
  .onScrollFrameBegin((offset: number, state: ScrollState) => {
    let retOffset = offset;
    let currOffset = this.scrollerForParent.currentOffset().yOffset;
    let newOffset = currOffset + offset;
    if (offset > 0) {
      if (this.scrollerForChild.isAtEnd()) {
        return { offsetRemain: offset };
      }
      if (newOffset > this.headerHeight) {
        retOffset = this.headerHeight - currOffset;
      }
      this.scrollerForChild.scrollBy(0, offset - retOffset);
    } else {
      if (this.scrollerForChild.currentOffset().yOffset <= 0) {
        return { offsetRemain: offset };
      }
      if (newOffset < this.headerHeight) {
        retOffset = this.headerHeight - currOffset;
      }
      this.scrollerForChild.scrollBy(0, offset - retOffset);
    }
    return { offsetRemain: retOffset };
  })
  .width("100%")
  .layoutWeight(1)
  .backgroundColor(0xDCDCDC)
}
.width("100%")
.height("100%")

} }

在HarmonyOS Next中,Scroll嵌套List滑动到底部数据未更新可能是由于布局测量未触发或List未重新渲染导致。检查是否在添加数据后正确调用了List组件的rebuild方法。确保数据源更新后使用@State或@Link修饰的变量触发了UI刷新。若使用LazyForEach,需确保itemGenerator函数能正确响应数据变化。可尝试在数据更新后手动调用this.controller.scrollToIndex()方法强制滚动刷新。

这个问题是由于Scroll嵌套List时,在数据更新后没有正确触发布布局重绘导致的。解决方案是在添加数据后手动调用scrollerForParent的scrollTo方法重新计算滚动区域。

修改Button的onClick事件处理如下:

.onClick(() => {
  const items = this.getData(this.arr.length, 10)
  this.arr.push(...items)
  // 添加这行代码强制刷新滚动区域
  this.scrollerForParent.scrollTo({xOffset: 0, yOffset: this.scrollerForParent.currentOffset().yOffset})
})

原理说明:

  1. 当List数据更新时,虽然内容增加了,但父Scroll没有自动感知到子组件的高度变化
  2. 手动调用scrollTo会触发Scroll组件的重新布局计算
  3. 保持当前yOffset不变,只是强制刷新滚动区域

这样修改后,添加数据时Scroll的内容区域就会自动扩展,达到图二的效果。

回到顶部