轻松上手-骨架屏后动画显示

markdown 复制代码
作者:狼哥
团队:坚果派
团队介绍:坚果派由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉。团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,目前已开发鸿蒙原生应用,三方库60+,欢迎交流。

介绍

​ 在移动应用开发中,采用骨架屏(Skeleton Screen)作为加载策略,具有显著的优势。首先,骨架屏能够即时反馈给用户页面正在加载中,有效缓解了因网络延迟或数据处理造成的"白屏"现象,提升了用户体验的流畅度与期待感。它以一种轻量级、占位符的形式预先展示页面结构,让用户对即将呈现的内容有所预期,减少了等待时的焦虑感。

​ 其次,骨架屏设计简洁且高度自定义,能够根据应用风格和页面布局灵活调整,保持界面的一致性和美观性。这种视觉上的连续性不仅增强了应用的品牌形象,也提升了用户对产品的信任度和好感度。

​ 再者,从性能优化的角度来看,骨架屏相比完整的页面内容加载更快,因为它仅包含基础的框架结构和动画效果,减少了初始加载的数据量,有助于提升应用的加载速度和响应能力。这对于提升用户留存率和转化率具有重要意义。

​ 综上所述,骨架屏作为现代移动应用设计中的一种高效加载策略,以其即时反馈、美化等待体验、提升性能及增强品牌一致性等优势,成为提升用户体验不可或缺的一环。

效果预览

知识点

1. 显式动画 (animateTo)
2. 组件内转场 (transition)
3. if/else:条件渲染
4. ForEach:循环渲染

工程目录

typescript 复制代码
├──entry/src/main/ets                        // 代码区
│  ├──components
│  │  └──TextAreaBuilder.ets				 // 骨架屏占位组件 
│  ├──entryability
│  │  └──EntryAbility.ets 
│  ├──pages
│  │  └──Index.ets                           // 首页
│  └──view
│     ├──GridSkeleton.ets              		 // Grid骨架图
│     ├──GridView.ets                 		 // Grid布局图
│     ├──ListSkeleton.ets                 	 // List骨架图
│     └──ListView.ets                  		 // List布局图
│     ├──SwiperSkeleton.ets                  // Swiper骨架图
│     └──SwiperView.ets                 	 // Swiper布局图
└──entry/src/main/resources                  // 应用资源目录

具体实现

​ 在HarmonyOS(鸿蒙系统)中实现骨架屏(Skeleton Screen)通常用于提升应用的加载体验,特别是在网络请求数据尚未返回时显示一个大致的页面框架,让用户知道页面正在加载中。下面介绍如何使用if/else渲染、foreach渲染、显式动画以及组件内转场等技术在HarmonyOS中实现骨架屏。

骨架屏基础设计

​ 设计你的骨架屏布局。骨架屏通常包括简单的线条、圆形等,以模拟最终加载完成后的页面结构。可以使用在TextAreaBuilder.ets里封装的textArea Builder来创建。

1. 骨架屏占位组件
typescript 复制代码
@Builder
export function textArea(
  width: number | Resource | string = '100%',
  height: number | Resource | string = '100%',
  borderRadius: Length | BorderRadiuses | LocalizedBorderRadiuses = 0,
  padding: Length | Padding | LocalizedPadding = 0,
  margin: Length | Padding | LocalizedPadding = 0) {
  Row()
    .width(width)
    .height(height)
    .backgroundColor('#FFF2F3F4')
    .borderRadius(borderRadius)
    .padding(padding)
    .margin(margin)
}
2. 首页

​ 首页由Swiper视图、Grid视图、List视图组成,各自布局和逻辑在各自上实现。

typescript 复制代码
@Entry
@Component
struct Index {
    build() {
    Column({ space: 20 }) {
      SwiperView()
      GridView()
      ListView()
    }
    .height('100%')
    .width('100%')
  }
}
3. Swiper实现

​ Swiper骨架图

typescript 复制代码
import { textArea } from '../components/TextAreaBuilder'
@Component
export struct SwiperSkeleton {
  build() {
    textArea('90%', px2vp(460), 16, 0, {top: 11})
  }
}

​ Swiper实现与布局

typescript 复制代码
  @State isLoadingSwiperData: boolean = true;
  aboutToAppear(): void {
    // 模拟异步回调
    setTimeout(() => {
      animateTo({ duration: 1000 }, () => {
        this.isLoadingSwiperData = false;
      })
    }, 4000)
  }
typescript 复制代码
  Swiper() {
    ForEach(this.bannerList, (item: BannerClass) => {
      if (this.isLoadingSwiperData) {
        SwiperSkeleton()
      } else {
        Image($r(item.imageSrc))
          .objectFit(ImageFit.Contain)
          .width('100%')
          .borderRadius(16)
          .transition({ type: TransitionType.Insert, translate: { x: 700, y: 0 } })
      }
    }, (item: BannerClass) => item.id.toString())
  }
4. Grid实现

​ Grid骨架图

typescript 复制代码
import { textArea } from '../components/TextAreaBuilder'
@Component
export struct GridSkeleton {
  build() {
    Column({space: 15}) {
      textArea('100%', '60%', { topLeft: 16, topRight: 16 })
      Column({space: 15}) {
        textArea('60%', '15%')
        textArea('90%', '25%')
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start)
      .padding({left: 15})
    }
    .height('100%')
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }
}

​ Grid实现与布局

typescript 复制代码
  @State isLoadingGridData: boolean = true;
  aboutToAppear(): void {
    // 模拟异步回调
    setTimeout(() => {
      animateTo({ duration: 3000 }, () => {
        this.isLoadingGridData = false;
      })
    }, 6000)
  }
typescript 复制代码
  Grid() {
    ForEach(this.enablementList, (item: ArticleClass) => {
      GridItem() {
        if (this.isLoadingGridData) {
          GridSkeleton()
        } else {
          EnablementItem({ enablementItem: item })
            .transition({ type: TransitionType.Insert, translate: { x: -700, y: 0 } })
        }

      }
      .width(160)
    }, (item: ArticleClass) => item.id.toString())
  }
5. List实现

​ List骨架图

typescript 复制代码
import { textArea } from '../components/TextAreaBuilder'
@Component
export struct ListSkeleton {
  build() {
    Row({space: 10}) {
      Column({space: 10}) {
        textArea('60%', '20%')
        textArea('90%', '70%')
      }
      .width('70%')
      .alignItems(HorizontalAlign.Start)
      textArea('30%', '100%', 16)
    }
    .height(88)
    .margin({ bottom: 10 })
    .justifyContent(FlexAlign.SpaceBetween)
  }
}

​ List实现与布局

typescript 复制代码
  @State isLoadingListData: boolean = true;
  aboutToAppear(): void {
    // 模拟异步回调
    setTimeout(() => {
      animateTo({ duration: 3000 }, () => {
        this.isLoadingListData = false;
      })
    }, 8000)
  }
typescript 复制代码
List({ space: 12 }) {
    ForEach(this.tutorialList, (item: ArticleClass) => {
      ListItem() {
        if (this.isLoadingListData) {
          ListSkeleton()
        } else {
          TutorialItem({ tutorialItem: item })
            .transition({ type: TransitionType.Insert, translate: { x: 0, y: 500 } })
        }
      }
    }, (item: ArticleClass) => item.id.toString())
  }

总结

​ 通过此案例,可以学习到显式动画知识点,全局animateTo显式动画接口来指定由于闭包代码导致的状态变化插入过渡动效。同属性动画,布局类改变宽高的动画,内容都是直接到终点状态。组件内转场主要通过transition属性配置转场参数,在组件插入和删除时显示过渡动效,主要用于容器组件中的子组件插入和删除时,提升用户体验。if/else条件渲染,可根据应用的不同状态,使用if、else和else if渲染对应状态下的UI内容。ForEach循环渲染,ForEach接口基于数组类型数据来进行循环渲染,需要与容器组件配合使用,且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。例如,ListItem组件要求ForEach的父容器组件必须为List组件。总之,以后在很多异步返回数据前,都可以先显示骨架屏,让用户知道页面正在加载中,在HarmonyOS中实现骨架屏需要结合布局设计、数据绑定、条件渲染、动画以及可能的组件内状态管理。

约束与限制

1.本示例仅支持标准系统上运行,支持设备:华为手机。

2.HarmonyOS系统:HarmonyOS NEXT Developer Beta1及以上。

3.DevEco Studio版本:DevEco Studio NEXT Developer Beta1及以上。

4.HarmonyOS SDK版本:HarmonyOS NEXT Developer Beta1 SDK及以上。

相关推荐
觉醒法师9 小时前
HarmonyOS开发 - 本地持久化之实现LocalStorage支持多实例
前端·javascript·华为·typescript·harmonyos
东林知识库12 小时前
2024年10月HarmonyOS应用开发者基础认证全新题库
学习·华为·harmonyos
ChinaDragonDreamer12 小时前
HarmonyOS:@Watch装饰器:状态变量更改通知
开发语言·harmonyos·鸿蒙
Lei活在当下17 小时前
【初探鸿蒙01】鸿蒙生态用开发白皮书V3.0解读
harmonyos
SameX18 小时前
实现多子类型输入法:如何在 HarmonyOS中加载不同的输入模式
harmonyos
SuperHeroWu720 小时前
【HarmonyOS】判断应用是否已安装
华为·微信·harmonyos·qq·微博·应用是否安装·canopenlink
SoraLuna20 小时前
「Mac畅玩鸿蒙与硬件7」鸿蒙开发环境配置篇7 - 使用命令行工具和本地模拟器管理项目
macos·华为·harmonyos
SuperHeroWu71 天前
【HarmonyOS】鸿蒙应用OAID广告标识ID设置设备唯一标识
华为·harmonyos·oaid·广告标识·跟踪权限
雪芽蓝域zzs1 天前
HarmonyOS 组件样式@Style 、 @Extend、自定义扩展(AttributeModifier、AttributeUpdater)
深度学习·harmonyos
佛山芃程科技1 天前
鸿蒙NEXT+Flutter开发7-存储应用设置项
harmonyos