鸿蒙开发网格和列表组件的使用

介绍

在上一节中,我们完成了单个组件的创建,在本节内容中我们会将子视图循环渲染、填入数据信息,分别形成网格和列表。在建立完成网格和列表后,它们会与最开始创建的运营推荐位合成完整的可滑动视图。

根据本教程进行学习,您可以选择从上一教程结束时构建完成的项目开始,也可以直接运行04_StartingPoint文件夹中的项目。

根据教程中的提示使用04_Resources文件夹中的文件。

如果您想要自行探索,可以直接打开04_Complete文件夹中的项目并浏览代码。

项目文件下载

下载项目文件并开始构建本项目。按照以下步骤操作:

04_BuildGridAndList.zip

建立文章展示的数据结构

我们需要先创建数据结构,并建立其对应的内容数组,以此来达成页面效果。

观察单个item视图,可以发现,每一个item是由其文章的对应标题(title)、简介(brief)、文章配图(imageSrc)和点击后即将跳转的网页地址(webUrl)组成的。

Step 1

创建文章的数据结构。在数据结构内为每个文章定义唯一id,并添加其标题(title)、简介(brief)、文章配图(imageSrc)和点击后即将跳转的网页地址(webUrl)属性。

 
  1. // src/main/ets/pages/Index.ets
  2. class BannerClass {
  3. ...
  4. }
  5. class ArticleClass {
  6. id: string = '';
  7. imageSrc: ResourceStr = '';
  8. title: string = '';
  9. brief: string = '';
  10. webUrl: string = '';
  11. constructor(id: string, imageSrc: ResourceStr, title: string, brief: string, webUrl: string) {
  12. this.id = id;
  13. this.imageSrc = imageSrc;
  14. this.title = title;
  15. this.brief = brief;
  16. this.webUrl = webUrl;
  17. }
  18. }

No Preview

Step 2

将04_Resources文件夹中的所有图片放置在src/main/resources/base/media路径下,我们可使用$r('app.media. filename')的方式将该路径下的图片读取到Image组件内。

Step 3

建立命名为EnablementView的空组件和TutorialView的空组件。

 
  1. // src/main/ets/pages/Index.ets
  2. @Component
  3. struct EnablementView{
  4. build() {
  5. }
  6. }
  7. @Component
  8. struct TutorialView{
  9. build() {
  10. }
  11. }

No Preview

Step 4

在Index文件中,定义出enablementList数据,其中包含多个ArticleClass实例。该实例在刚刚的描述中包括id、图片地址,标题,简介,以及跳转地址数据。开发者可以复制右侧代码的内容。

 
  1. // src/main/ets/pages/Index.ets
  2. @Component
  3. struct EnablementView {
  4. @State enablementList: Array<ArticleClass> = [
  5. new ArticleClass('1', $r('app.media.enablement_pic1'), 'HarmonyOS第一课',
  6. '基于真实的开发场景,提供向导式学习,多维度融合课程等内容,给开发者提供全新的学习体验。',
  7. 'https://developer.huawei.com/consumer/cn/doc/harmonyos-video-courses/video-tutorials-0000001443535745'),
  8. new ArticleClass('2', $r('app.media.enablement_pic2'), '开发指南',
  9. '提供系统能力概述、快速入门,用于指导开发者进行场景化的开发。指南涉及到的知识点包括必要的背景知识、符合开发者实际开发场景的操作任务流(开发流程、开发步骤、调测验证)以及常见问题等。',
  10. 'https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/application-dev-guide-0000001630265101'),
  11. new ArticleClass('3', $r('app.media.enablement_pic3'), '最佳实践',
  12. '针对新发布特性及热点特性提供详细的技术解析和开发最佳实践。',
  13. 'https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/topic-architecture-0000001678045510'),
  14. new ArticleClass('4', $r('app.media.enablement_pic4'), 'Codelabs',
  15. '以教学为目的的代码样例及详细的开发指导,帮助开发者一步步地完成指定场景的应用开发并掌握相关知识。Codelabs将最新的鸿蒙生态应用开发技术与典型场景结合,让开发者快速地掌握开发高质量应用的方法。同时支持互动式操作,通过文字、代码和效果联动为开发者带来更佳的学习体验。',
  16. 'https://developer.huawei.com/consumer/cn/doc/harmonyos-codelabs/codelabs-0000001443855957'),
  17. new ArticleClass('5', $r('app.media.enablement_pic5'), 'Sample',
  18. '面向不同类型的开发者提供的鸿蒙生态应用开发优秀实践,每个Sample Code都是一个可运行的工程,为开发者提供实例化的代码参考。',
  19. 'https://developer.huawei.com/consumer/cn/doc/harmonyos-samples/samples-0000001162414961'),
  20. new ArticleClass('6', $r('app.media.enablement_pic6'), 'API参考',
  21. '面向开发者提供鸿蒙系统开放接口的全集,供开发者了解具体接口使用方法。API参考详细地描述了每个接口的功能、使用限制、参数名、参数类型、参数含义、取值范围、权限、注意事项、错误码及返回值等。',
  22. 'https://developer.huawei.com/consumer/cn/doc/harmonyos-references/development-intro-0000001580026066'),
  23. new ArticleClass('7', $r('app.media.enablement_pic7'), 'FAQ',
  24. '开发者常见问题的总结,开发者可以通过FAQ更高效地解决常见问题。FAQ会持续刷新,及时呈现最新的常见问题。',
  25. 'https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs/faqs-development-0000001753952202'),
  26. new ArticleClass('8', $r('app.media.enablement_pic8'), '开发者论坛', '和其他应用开发者交流技术、共同进步。',
  27. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  28. ];
  29. build() {
  30. // ...
  31. }
  32. }

No Preview

Step 5

同样的,我们在Index文件中,定义出tutorialList数据,开发者可以直接复制右侧的代码内容到自己的代码中。

 
  1. // src/main/ets/pages/Index.ets
  2. @Component
  3. struct TutorialView {
  4. @State tutorialList: Array<ArticleClass> = [
  5. new ArticleClass('1', $r('app.media.tutorial_pic1'), 'Step1 环境的搭建',
  6. '本篇教程实现了快速入门——一个用于了解和学习HarmonyOS的应用程序。',
  7. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  8. new ArticleClass('2', $r('app.media.tutorial_pic2'), 'Step2 使用Swiper构建运营广告位',
  9. 'Swiper组件提供滑动轮播显示的能力。Swiper本身是一个容器组件,当设置了多个子组件后,可以对这些子组件进行轮播显示。',
  10. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  11. new ArticleClass('3', $r('app.media.tutorial_pic3'), 'Step3 创建和组合视图',
  12. 'Item定义子组件相关特征。相关组件支持使用条件渲染、循环渲染、懒加载等方式生成子组件。',
  13. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  14. new ArticleClass('4', $r('app.media.tutorial_pic4'), 'Step4 网格和列表组建的使用',
  15. '网格和列表组件中,当Item达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能,适合用于呈现同类数据类型或数据类型集',
  16. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  17. new ArticleClass('5', $r('app.media.tutorial_pic5'), 'Step5 应用架构设计基础',
  18. 'ArkUI采取MVVM = Model + View + ViewModel模式,将数据与视图绑定在一起,更新数据的时候直接更新视图。',
  19. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  20. new ArticleClass('6', $r('app.media.tutorial_pic6'), 'Step6 ArkWeb页面适配',
  21. 'ArkWeb(方舟Web)提供了Web组件,用于在应用程序中显示Web页面内容,为开发者提供页面加载、页面交互、页面调试等能力。',
  22. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  23. new ArticleClass('7', $r('app.media.tutorial_pic7'), 'Step7 数据驱动UI更新', '数据更新的同时会直接驱动UI的改变',
  24. 'xxx'),
  25. new ArticleClass('8', $r('app.media.tutorial_pic8'), 'Step8 设置组件导航',
  26. 'Navigation组件适用于模块内页面切换,一次开发,多端部署场景。通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式来呈现更好的标题和内容联动效果。',
  27. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  28. new ArticleClass('9', $r('app.media.tutorial_pic8'), 'Step9 原生智能:AI语音朗读',
  29. '文本转语音服务提供将文本信息转换为语音并进行播报的能力,便于用户与设备进行互动,实现实时语音交互,文本播报。',
  30. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  31. new ArticleClass('10', $r('app.media.tutorial_pic8'), 'Step10 原生互联:分布式流转',
  32. '流转能力打破设备界限,多设备联动,使用户应用程序可分可合、可流转,实现如邮件跨设备编辑、多设备协同健身、多屏游戏等分布式业务。',
  33. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  34. new ArticleClass('11', $r('app.media.tutorial_pic8'), 'Step11 一次开发,多端部署',
  35. '一套代码工程,一次开发上架,多端按需部署。支撑开发者快速高效的开发支持多种终端设备形态的应用,实现对不同设备兼容的同时,提供跨设备的流转、迁移和协同的分布式体验。',
  36. 'https://developer.huawei.com/consumer/cn/forum/home?all=1'),
  37. ];
  38. build() {
  39. // ...
  40. }
  41. }

No Preview

实现赋能套件区域

在本小节内容中,我们将创建网格布局。网格布局是由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。网格布局具有较强的页面均分能力,子组件占比控制能力,是一种重要自适应布局。

Step 1

网格布局将区域分割成行与列构成的多个区块,其外部由Gird组件进行包裹,内部子组件只能为GridItem组件,即网格中每一个被分割的区块为一个GridItem。

Step 2

根据设计图可以看到,赋能套件区域主要由两部分构成,呈上下排列,所以可以考虑使用Column组件来作为外层容器,上面部分为“赋能套件”文字,该部分内容呈横向地排布。下面的部分为可以滑动的所有赋能套件内容。

Step 3

首先我们可以先将之前创建好的EnablementView与TutorialView,放入到Index组件中,此处采用Scroll作为外层容器,是由于其内部内容很有可能会超过屏幕高度,为保证内容显示,可以采用Scroll组件来进行滚动显示。scrollBar设置为BarState.Off,表示关闭滚动时的滚动条显示。注意,此处的Sroll组件要替换原本的Banner组件。

 
  1. // src/main/ets/pages/Index.ets
  2. @Entry
  3. @Component
  4. struct Index {
  5. @State message: string = '快速入门';
  6. build() {
  7. Column() {
  8. Text(this.message)
  9. ...
  10. Scroll() {
  11. Column() {
  12. Banner()
  13. EnablementView()
  14. TutorialView()
  15. }
  16. }
  17. .layoutWeight(1)
  18. .scrollBar(BarState.Off)
  19. .align(Alignment.TopStart)
  20. }
  21. ...
  22. }
  23. }

No Preview

Step 4

然后回到我们的EnablementView组件,经过刚刚的分析,我们发现可以使用Column组件来作为外层容器。我们设置Column组件与其上元素的间距为18,设置Column元素的交叉轴也就是横向方向上元素的对齐方式为从左至右的布局。

由于我们后续会引用EnablementView,所以需要将该组件使用export导出。

 
  1. // src/main/ets/pages/Index.ets
  2. @Preview
  3. @Component
  4. export struct EnablementView {
  5. @State enablementList: Array<ArticleClass> = ...;
  6. build() {
  7. Column() {
  8. }
  9. .margin({ top: 18 })
  10. .alignItems(HorizontalAlign.Start)
  11. .width('100%')
  12. }
  13. }
  14. // ...

No Preview

Step 5

接着我们使用Text组件来加载“赋能套件”的文字。并配置字体进行美观地显示。

 
  1. // src/main/ets/pages/Index.ets
  2. @Preview
  3. @Component
  4. export struct EnablementView {
  5. @State enablementList: Array<ArticleClass> = ...;
  6. build() {
  7. Column() {
  8. Text('赋能套件')
  9. .fontColor('#182431')
  10. .fontSize(16)
  11. .fontWeight(500)
  12. .fontFamily('HarmonyHeiTi-medium')
  13. .textAlign(TextAlign.Start)
  14. .padding({ left: 16 })
  15. .margin({ bottom: 8.5 })
  16. }
  17. ...
  18. }
  19. }
  20. // ...

Preview

Step 6

接着我们需要修改一下EnablementItem组件,在之前的内容中,我们通过定义成员变量的方式定义了title和brief,此处我们需要通过外部传值来控制EnablementItem的显示内容,所以我们使用了@Prop装饰器,该装饰器用于从父组件接收数据。同时我们也修改各个组件的渲染数据源,使用由父组件传递而来的数据。此时可以删除之前作为示例文本的title和brief变量。注意此处加入@Prop后,Previewer会失效,建议开发者直接删掉原来的加在EnablementItem组件上的@Preview装饰器。

 
  1. @Component
  2. export struct EnablementItem {
  3. @Prop enablementItem: ArticleClass;
  4. build() {
  5. Column() {
  6. Image(this.enablementItem.imageSrc)
  7. ..
  8. Text(this.enablementItem.title)
  9. ...
  10. Text(this.enablementItem.brief)
  11. ...
  12. }
  13. ...
  14. }
  15. }

No Preview

Step 7

然后我们使用Grid组件作为外层容器,包裹之后的GridItem。rowsTemplate和columnsTemplate属性值是一个由多个空格和'数字+fr'间隔拼接的字符串,fr的个数即网格布局的行或列数,fr前面的数值大小,用于计算该行或列在网格布局宽度上的占比,最终决定该行或列宽度。scrollBar用于关闭滚动条。

 
  1. // src/main/ets/pages/Index.ets
  2. @Preview
  3. @Component
  4. export struct EnablementView {
  5. @State enablementList: Array<ArticleClass> = ...;
  6. build() {
  7. Column() {
  8. Text('赋能套件')
  9. ...
  10. Grid() {
  11. }
  12. .rowsTemplate('1fr')
  13. .columnsGap(8)
  14. .scrollBar(BarState.Off)
  15. .height(169)
  16. .padding({ top: 2, left: 16, right: 16 })
  17. }
  18. ...
  19. }
  20. }
  21. // ...

No Preview

Step 8

最后,我们就可以使用ForEach组件构建出所有的GirdItem,将EnablementItem作为GridItem的子组件,并将enablementList每一项的内容作为参数传递给EnablementItem组件进行渲染。至此我们的赋能套件区域的效果就实现了。

 
  1. // src/main/ets/pages/Index.ets
  2. @Preview
  3. @Component
  4. export struct EnablementView {
  5. @State enablementList: Array<ArticleClass> = ...;
  6. build() {
  7. Column() {
  8. Text('赋能套件')
  9. ...
  10. Grid() {
  11. ForEach(this.enablementList, (item: ArticleClass) => {
  12. GridItem() {
  13. EnablementItem({ enablementItem: item })
  14. }
  15. }, (item: ArticleClass) => item.id)
  16. }
  17. ...
  18. }
  19. ...
  20. }
  21. }
  22. // ...

Preview

实现入门教程区域

在本小节内容中,我们将创建列表布局。列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,使用列表可以轻松高效地显示结构化、可滚动的信息。

Step 1

根据设计图,我们入门教程区域也是由上至下的布局,也可以考虑采用Column组件作为外部容器组件。其中包含一行文本,以及多个结构类似的内容,我们就可以采用List组件进行组织。

Step 2

根据刚刚的分析,我们最外层采用Column进行包裹,和刚刚的内容一样,设置Column离上面的元素为18的间距,设置Column的侧轴对齐方式为从左至右。

 
  1. // src/main/ets/pages/Index.ets
  2. @Preview
  3. @Component
  4. struct TutorialView {
  5. @State tutorialList: Array<ArticleClass> = ...;
  6. build() {
  7. Column() {
  8. }
  9. .margin({ top: 18 })
  10. .alignItems(HorizontalAlign.Start)
  11. }
  12. }

No Preview

Step 3

首先让我们实现入门教程的文本,使用Text组件加载“入门教程”,同样的使用文本的各项属性使得文本美观地进行展示。

 
  1. // src/main/ets/pages/Index.ets
  2. @Preview
  3. @Component
  4. struct TutorialView {
  5. @State tutorialList: Array<ArticleClass> = ...;
  6. build() {
  7. Column() {
  8. Text('入门教程')
  9. .fontColor('#182431')
  10. .fontSize(16)
  11. .fontWeight(500)
  12. .fontFamily('HarmonyHeiTi-medium')
  13. .textAlign(TextAlign.Start)
  14. .padding({ left: 16 })
  15. .margin({ bottom: 8.5 })
  16. }
  17. .margin({ top: 18 })
  18. .alignItems(HorizontalAlign.Start)
  19. }
  20. }

Preview

Step 4

List组件适合用于呈现同类数据类型或数据类型集,例如此处的tutorialList,为同一类型的集合,此处我们使用List组件作为外层容器。

 
  1. // src/main/ets/pages/Index.ets
  2. @Preview
  3. @Component
  4. struct TutorialView {
  5. @State tutorialList: Array<ArticleClass> = ...;
  6. build() {
  7. Column() {
  8. Text('入门教程')
  9. ...
  10. List({ space: 12 }) {
  11. }
  12. .scrollBar(BarState.Off)
  13. .padding({ left: 16, right: 16 })
  14. }
  15. ...
  16. }
  17. }

No Preview

Step 5

同样的,此时需要我们切回到TutorialItem组件,和之前的内容一样,我们需要修改TutorialItem为从外部进行参数传递,也需要修改其中组件加载的资源内容。此时可以删除之前作为示例文本的title和brief变量。同样的,也需要开发者手动删除加在TutorialItem组件上的@Preview装饰器。

 
  1. @Component
  2. export struct TutorialItem {
  3. @Prop tutorialItem: ArticleClass;
  4. build() {
  5. Row() {
  6. Column() {
  7. Text(this.tutorialItem.title)
  8. ...
  9. Text(this.tutorialItem.brief)
  10. ...
  11. }
  12. ...
  13. Image(this.tutorialItem.imageSrc)
  14. ...
  15. }
  16. ...
  17. }
  18. }

No Preview

Step 6

最后我们使用ForEach循环渲染TutorialItem,即可达成如图所示的界面效果。

 
  1. // src/main/ets/pages/Index.ets
  2. @Preview
  3. @Component
  4. struct TutorialView {
  5. @State tutorialList: Array<ArticleClass> = ...;
  6. build() {
  7. Column() {
  8. Text('入门教程')
  9. ...
  10. List({ space: 12 }) {
  11. ForEach(this.tutorialList, (item: ArticleClass) => {
  12. ListItem() {
  13. TutorialItem({ tutorialItem: item })
  14. }
  15. }, (item: ArticleClass) => item.id)
  16. }
  17. .scrollBar(BarState.Off)
  18. .padding({ left: 16, right: 16 })
  19. }
  20. .margin({ top: 18 })
  21. }
  22. }
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    code_shenbing

    你的鼓励将是我创作的最大动力

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值