HarmonyOS鸿蒙Next中ListItem底部触底加载LoadingProgress()动画失效

HarmonyOS鸿蒙Next中ListItem底部触底加载LoadingProgress()动画失效 封装了一个loading的加载效果再拿到ListItem中使用的时候发现动画效果失效了

cke_187.png cke_534.png


更多关于HarmonyOS鸿蒙Next中ListItem底部触底加载LoadingProgress()动画失效的实战教程也可以访问 https://www.itying.com/category-93-b0.html

12 回复

背景知识:

楼主在使用list+listIltem时,要注意一下边距问题。从上述你得代码调试过程中可以知道,Loading中添加了.margin({right:’-100%”])出现的问题,只要在源码基础上注释掉这个就可以了,但是注释掉后又会出现 Loading布局居左问题。建议楼主使用grid布局来进行网络布局。

问题解决:

代码实例:

interface ItemType {
    name: string
    age: number
}


@Component
export struct Loading {
    @Prop isAllShow: boolean

    build() {
        if (this.isAllShow) {
            Row() {
                Text(`没有更多啦`)
                    .fontSize(14)
                    .fontColor('#BD4B1F')
            }
            .width('100%')
            .height(30)
            .justifyContent(FlexAlign.Center)
            .margin({ top: 2 })
        } else {
            Row({ space: 5 }) {
                Text('加载中')
                    .fontSize(9)
                    .fontColor('#BD4B1F')
                LoadingProgress()
                    .width("30")
                    .height("30")
                    .color("#BD4B1F")
            }
            .height(30)
            .width('100%')
            .height("50")
            .margin({ top: 5 })
            .justifyContent(FlexAlign.Center)
        }


    }
}


@Entry
@Component
struct LoadingPage {
    @State message: string = 'Hello World';
    @State person: ItemType[] = [
        { name: "张三", age: 20 },
        { name: "李四", age: 22 },
        { name: "王五", age: 19 },
        { name: "赵六", age: 21 },
        { name: "钱七", age: 23 },
        { name: "孙八", age: 20 },
        { name: "周九", age: 24 },
        { name: "吴十", age: 18 },
        { name: "郑十一", age: 22 },
        { name: "王十二", age: 21 },
        { name: "刘十三", age: 19 },
        { name: "陈十四", age: 20 },
        { name: "杨十五", age: 25 },
        { name: "黄十六", age: 22 },
        { name: "赵十七", age: 18 },
        { name: "林十八", age: 21 },
        { name: "张十九", age: 23 },
        { name: "李二十", age: 20 },
        { name: "王二一", age: 19 },
        { name: "刘二二", age: 22 }
    ]

    pushList() {
        setTimeout(() => {
            for (let i = 0; i < 20; i++) {
                this.person.push({ name: `张三${i}`, age: i })
            }
        }, 2000)
    }

    build() {
        Column() {
            List() {
                ForEach(this.person, (item: ItemType, index) => {
                    ListItem() {
                        Column() {
                            Row() {
                                Text('姓名:')
                                Text(item.name)
                                Text((index + 1).toString())
                                    .margin({ left: 20 })
                            }

                            Row() {
                                Text('年龄:')
                                Text(item.age.toString())
                            }
                        }
                        .margin({ bottom: 20 })
                        .backgroundColor('#BD4B1F')
                    }
                })
                ListItem() {
                    Loading({ isAllShow: false })
                }
                .height(50)
            }
            .lanes(2)
            .onReachEnd(() => {
                this.pushList()
            })

        }
    }
}

真机演示:

cke_1730.gif

更多关于HarmonyOS鸿蒙Next中ListItem底部触底加载LoadingProgress()动画失效的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


感谢兄弟给的提示,解决办法已经找到了,采用ListItemGroup解决了,

图片

问题已解决,将ListItem替换为ListItemGroup

这里的.margin({right: ‘-100%’})不删除是因为需要保持其“加载中”处于页面中间

ListItemGroup(){
  Loading({isAllShow: false})
    .margin({right: '-100%'})
}
.height(50)
/*ListItem(){
  Loading({isAllShow: false})
    .margin({right: '-100%'})
}
.height(50)*/

图片

这是你提供的代码运行结果截图,未发现你所说的未见loading

按照下面改一下代码

1/ 删除异常边距

ListItem(){

  Loading({isAllShow: false})

  // 这个边距删除

}

.height(50)

2/ 在封装组件中添加尺寸

LoadingProgress()

  .color("#BD4B1F")

  .width(30) // 增加尺寸

  .height(30)

3/ 使用标准列表布局并开启滚动事件

List()

  .width('100%')

  .height('100%')

  .onScrollIndex((start: number, end: number) => {

    if (end >= this.person.length - 1) {

      this.pushList()

    }

  })

4/ 添加加载状态控制

@State isLoadMore: boolean = false

pushList() {

  if (this.isLoadMore) return

  this.isLoadMore = true

  setTimeout(() => {

    // 加载数据

    this.isLoadMore = false

  }, 2000)

}

感谢您的提问,为了更快解决您的问题,麻烦请补充以下信息:

完整的复现demo(通过描述中提供的代码未复现问题,加载动画正常)。

@Component
export struct Loading {
  @Prop isAllShow: boolean
  build() {
    if (this.isAllShow) {
      Row() {
        Text(`没有更多啦`)
          .fontSize(14)
          .fontColor('#BD4B1F')
      }
      .width('100%')
      .height(30)
      .justifyContent(FlexAlign.Center)
      .margin({ top: 2 })
    } else {
      Row({ space: 5 }) {
        Text('加载中')
          .fontSize(9)
          .fontColor('#BD4B1F')
        LoadingProgress()
          .color("#BD4B1F")
      }
      .height(30)
      .width('100%')
      .margin({ top: 5 })
      .justifyContent(FlexAlign.Center)
    }
  }
}

import { Loading } from "./Loading"

interface ItemType {
  name: string
  age: number
}

@Entry
@Component
struct Index {
  @State person: ItemType[] = [
    { name: "张三", age: 20 },
    { name: "李四", age: 22 },
    { name: "王五", age: 19 },
    { name: "赵六", age: 21 },
    { name: "钱七", age: 23 },
    { name: "孙八", age: 20 },
    { name: "周九", age: 24 },
    { name: "吴十", age: 18 },
    { name: "郑十一", age: 22 },
    { name: "王十二", age: 21 },
    { name: "刘十三", age: 19 },
    { name: "陈十四", age: 20 },
    { name: "杨十五", age: 25 },
    { name: "黄十六", age: 22 },
    { name: "赵十七", age: 18 },
    { name: "林十八", age: 21 },
    { name: "张十九", age: 23 },
    { name: "李二十", age: 20 },
    { name: "王二一", age: 19 },
    { name: "刘二二", age: 22 }
  ]

  pushList() {
    setTimeout(() => {
      for (let i = 0; i < 20; i++) {
        this.person.push({name: `张三${i}`, age: i})
      }
    }, 2000)
  }

  build() {
    Column() {
      List() {
        ForEach(this.person, (item: ItemType, index) => {
          ListItem() {
            Column() {
              Row() {
                Text('姓名:')
                Text(item.name)
                Text((index + 1).toString())
                  .margin({ left: 20 })
              }

              Row() {
                Text('年龄:')
                Text(item.age.toString())
              }
            }
            .margin({ bottom: 20 })
            .backgroundColor('#BD4B1F')
          }
        })
        ListItem(){
          Loading({isAllShow: false})
            .margin({right: '-100%'})
        }
        .height(50)
      }
      .lanes(2)
      .onReachEnd(() => {
        this.pushList()
      })
    }
  }
}

未复现问题,使用以上demo加载动效正常。建议将IDE升级到最新版本进行测试。

demo给全了没

.lanes(2, 10)
        .margin({ top: 20, bottom: 135 })
        .onReachEnd(() => {
        })

在HarmonyOS Next中,ListItem底部触底加载时LoadingProgress动画失效,通常与List组件的onReachEnd事件触发机制或LoadingProgress组件的状态管理有关。需检查onReachEnd回调是否正确执行,并确保LoadingProgress的显示状态(如通过@State控制)在触底时被正确更新。同时,确认List容器的布局和滚动事件是否正常。

在HarmonyOS Next中,LoadingProgress()动画在ListItem底部失效,通常是由于ListItem的复用机制和渲染优化导致的。List组件默认会回收屏幕外的ListItem以提升性能,这可能中断或重置正在进行的动画。

核心解决方案是确保动画组件在ListItem中具有稳定的状态管理。 以下是最直接有效的修复方法:

  1. 使用if条件控制加载组件的渲染:将LoadingProgress包裹在条件渲染逻辑中,确保仅在加载状态激活时创建动画实例,避免复用导致的动画重置。

    List() {
      ForEach(this.data, (item: DataType) => {
        ListItem() {
          // 正常列表项内容
        }
      })
      // 底部加载组件
      if (this.isLoading) { // 使用状态变量控制
        ListItem() {
          LoadingProgress()
            .width(50)
            .height(50)
        }
      }
    }
    

    isLoading状态变为true时,ListItem会创建并开始动画;变为false时,组件销毁。这能确保动画每次都能正确初始化并播放。

  2. 为加载项设置明确的key:如果加载组件是独立的ListItem,为其分配一个固定且唯一的key,防止列表在更新时错误复用该项。

    if (this.isLoading) {
      ListItem() {
        LoadingProgress()
      }
      .key('loading_indicator') // 设置固定key
    }
    
  3. 检查状态更新与List的交互:确保触发加载的isLoading状态变更是在主线程同步更新的,并且List的数据源(this.data)没有在加载过程中发生非预期的清空或重置,这可能导致整个列表重绘并打断动画。

根本原因:直接放置在ListItem中的LoadingProgress,在列表滚动或数据更新时,可能因为ListItem的实例被回收并用于渲染其他数据项,导致其内部动画状态被销毁。使用条件渲染是标准做法,它明确了该组件的生命周期与加载状态的绑定关系。

请优先采用第一种方案,它能最稳定地解决此问题。

回到顶部