HarmonyOS鸿蒙Next中ArkTS如何实现骨架屏(Skeleton Loading)效果?
HarmonyOS鸿蒙Next中ArkTS如何实现骨架屏(Skeleton Loading)效果? 在 ArkTS 中如何实现骨架屏(Skeleton Loading)效果,列表加载时显示灰色占位块,提升用户体验。
7 回复
开发者您好,如下提供LazyForEach实现骨架屏预加载的方案:
【解决方案】
- 使用LazyForEach对数据源中的每个数据进行预加载。
- 在Stack组件中,首先设置背景色为rgba(0,0,0,0.1),然后通过linearGradient设置组件的颜色渐变效果,并结合animation方法设置动画的持续时间和循环次数。
// 用户自定义数据源
class MyDataSourceLOne implements IDataSource {
private list: number[] = [];
constructor(list: number[]) {
this.list = list;
}
totalCount(): number {
return this.list.length;
}
getData(index: number): number {
return this.list[index];
}
registerDataChangeListener(): void {
}
unregisterDataChangeListener() {
}
}
@Entry
@Component
struct BackGroundColorGradualChange {
private arr: MyDataSourceLOne = new MyDataSourceLOne([]);
private listScroller: ListScroller = new ListScroller();
@State translateX: string = '-100%';
aboutToAppear(): void {
let list: number[] = [];
for (let i = 1; i <= 7; i++) {
list.push(i);
}
this.arr = new MyDataSourceLOne(list);
}
build() {
Column() {
List({ space: 20, initialIndex: 100, scroller: this.listScroller }) {
LazyForEach(this.arr, () => {
ListItem() {
Stack() {
// 设置组件的背景色
Text()
.width('100%')
.height(100)
.backgroundColor('rgba(0,0,0,0.1)');
Text()
.width('100%')
.height(100)
.translate({ x: this.translateX })
.onAppear(() => {
this.translateX = '100%';
})
// 设置动画的持续时间和循环次数
.animation({
duration: 1500,
iterations: -1
})
// 设置颜色渐变效果
.linearGradient({
angle: 90,
colors: [
['rgba(255,255,255,0)', 0],
['rgba(255,255,255,1)', 0.5],
['rgba(255,255,255,0)', 1]
]
});
}
.width('100%')
.height(100)
.backgroundColor(0xFFFFFF);
};
});
}
.listDirection(Axis.Vertical)
.scrollBar(BarState.Off)
.friction(0.6)
.edgeEffect(EdgeEffect.Spring)
.width('90%')
.cachedCount(3);
}
.width('100%')
.height('100%')
.backgroundColor(0xDCDCDC)
.padding({ top: 5 });
}
}
【背景知识】
- LazyForEach为开发者提供了基于数据源渲染出一系列子组件的能力。当在滚动容器中使用了LazyForEach,框架会根据滚动容器可视区域按需创建组件,当组件滑出可视区域外时,框架会销毁并回收组件以降低内存占用。
- 骨架屏通过显示简单的灰色块和线条,让用户在等待内容加载时获得视觉反馈。
更多关于HarmonyOS鸿蒙Next中ArkTS如何实现骨架屏(Skeleton Loading)效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
基本实现步骤
1. 定义加载状态变量
@State isLoading: boolean = true;
2. 编写骨架屏组件(可复用)
@Component
struct SkeletonItem {
build() {
Column() {
// 标题骨架
Row()
.width('80%')
.height(20)
.backgroundColor('#e0e0e0')
.borderRadius(4)
// 内容骨架
Row()
.width('100%')
.height(16)
.margin({ top: 8 })
.backgroundColor('#e0e0e0')
.borderRadius(4)
Row()
.width('60%')
.height(16)
.margin({ top: 4 })
.backgroundColor('#webtoken')
.borderRadius(4)
}
.padding(16)
.backgroundColor('#f5f5f5')
.borderRadius(8)
}
}
3. 在主页面中根据状态切换显示
@Entry
@Component
struct MainPage {
@State isLoading: boolean = true;
private data: string = '';
aboutToAppear() {
// 模拟网络请求
setTimeout(() => {
this.data = '加载完成的内容';
this.isLoading = false;
}, 2000);
}
build() {
Column() {
if (this.isLoading) {
// 显示骨架屏
Column() {
ForEach(Array(3), (_, index) => {
SkeletonItem()
.margin({ bottom: 12 })
})
}
.padding(16)
} else {
// 显示真实内容
Text(this.data)
.fontSize(18)
.padding(16)
}
}
.width('100%')
.height('100%')
}
}
在HarmonyOS Next中,ArkTS可通过@Builder装饰器构建骨架屏组件。主要步骤包括:使用Column、Row等布局容器模拟内容结构,通过Rectangle组件绘制占位块,并设置其宽度、高度、圆角及背景色(通常为浅灰色)。利用@State装饰的状态变量控制骨架屏的显示与隐藏。加载数据时显示骨架屏,数据加载完成后切换为实际内容。可通过animation属性添加简单的透明度或平移动画增强视觉效果。
在HarmonyOS Next的ArkTS中,可以通过以下方式实现骨架屏效果:
1. 使用条件渲染控制显示
// 数据加载状态
@State isLoading: boolean = true
@State listData: Array<Object> = []
// 模板部分
if (this.isLoading) {
// 显示骨架屏
SkeletonView()
} else {
// 显示实际内容
RealContentView()
}
2. 创建骨架屏组件
@Component
struct SkeletonItem {
build() {
Column() {
// 头像占位
Row()
.width(80)
.height(80)
.backgroundColor('#E0E0E0')
.borderRadius(40)
// 文本占位
Column() {
Row()
.width('60%')
.height(20)
.backgroundColor('#E0E0E0')
.margin({ top: 10 })
Row()
.width('40%')
.height(15)
.backgroundColor('#E0E0E0')
.margin({ top: 8 })
}
}
.padding(12)
}
}
3. 添加加载动画效果
// 使用动画增强效果
@State opacityValue: number = 0.5
aboutToAppear() {
// 创建脉动动画
setInterval(() => {
this.opacityValue = this.opacityValue === 0.5 ? 0.8 : 0.5
}, 1000)
}
// 在骨架屏元素上应用
Row()
.opacity(this.opacityValue)
.animation({ duration: 1000, curve: Curve.EaseInOut })
4. 列表骨架屏实现
@Component
struct SkeletonList {
build() {
List() {
ForEach(Array.from({ length: 5 }), (item, index) => {
ListItem() {
SkeletonItem()
}
})
}
}
}
5. 实际应用示例
@Component
struct ContentPage {
@State isLoading: boolean = true
@State dataList: Array<any> = []
aboutToAppear() {
// 模拟数据加载
setTimeout(() => {
this.dataList = this.fetchData()
this.isLoading = false
}, 2000)
}
build() {
Column() {
if (this.isLoading) {
SkeletonList()
} else {
RealList({ data: this.dataList })
}
}
}
}
关键要点:
- 使用条件渲染切换骨架屏和真实内容
- 骨架屏样式应模拟真实内容的布局结构
- 可添加淡入淡出或脉动动画提升体验
- 保持骨架屏与真实内容的尺寸一致
- 在数据加载完成后平滑过渡到真实内容
这种实现方式能有效提升加载时的用户体验,避免页面空白或布局跳动。





