ToB企服应用市场:ToB评测及商务社交产业平台

标题: 鸿蒙实战开发-使用常用组件与结构实现登录、首页、我的三个页面 [打印本页]

作者: 王海鱼    时间: 2024-6-21 19:21
标题: 鸿蒙实战开发-使用常用组件与结构实现登录、首页、我的三个页面
先容

HarmonyOS ArkUI提供了丰富多样的UI组件,您可以使用这些组件轻松地编写出更加丰富、漂亮的界面。在本篇Codelab中,您将通过一个简朴的购物交际应用示例,学习如何使用常用的底子组件和容器组件。
本示例重要包罗:“登录”、“首页”、“我的”三个页面,结果图如下:

相关概念


环境搭建

软件要求


硬件要求


环境搭建

完本钱篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤举行:

2.搭建烧录环境。
3.搭建开发环境。
代码结构解读

本篇Codelab只对核心代码举行讲解。
  1. ├──entry/src/main/ets              // 代码区
  2. │  ├──common
  3. │  │  └──constants
  4. │  │     └──CommonConstants.ets    // 公共常量类
  5. │  ├──entryability
  6. │  │  └──EntryAbility.ts           // 程序入口类
  7. │  ├──pages
  8. │  │  ├──LoginPage.ets             // 登录界面
  9. │  │  └──MainPage.ets                   // 主界面       
  10. │  ├──view
  11. │  │  ├──Home.ets                  // 首页
  12. │  │  └──Setting.ets               // 设置页
  13. │  └──viewmodel
  14. │     ├──ItemData.ets              // 列表数据实体类
  15. │     └──MainViewModel.ets         // 主界面视图Model
  16. └──entry/src/main/resources        // 应用资源目录
复制代码
实现“登录”页面

本节重要先容“登录”页面的实现,结果图如下:

界面使用Column容器组件结构,由Image、Text、TextInput、Button、LoadingProgress等底子组件构成,重要代码如下:
  1. // LoginPage.ets
  2. @Entry
  3. @Component
  4. struct LoginPage {
  5.   ...
  6.   build() {
  7.     Column() {
  8.       Image($r('app.media.logo'))
  9.        ...
  10.       Text($r('app.string.login_page'))
  11.         ...
  12.       Text($r('app.string.login_more'))
  13.         ...
  14.       TextInput({ placeholder: $r('app.string.account') })
  15.         ...
  16.       TextInput({ placeholder: $r('app.string.password') })
  17.         ...
  18.       Row() {
  19.         Text($r('app.string.message_login')).blueTextStyle()
  20.         Text($r('app.string.forgot_password')).blueTextStyle()
  21.       }
  22.       ....
  23.       Button($r('app.string.login'), { type: ButtonType.Capsule })
  24.         ....
  25.       Text($r('app.string.register_account'))
  26.         ....
  27.       if (this.isShowProgress) {
  28.         LoadingProgress()
  29.           ....
  30.       }
  31.       Blank()
  32.       Text($r('app.string.other_login_method'))
  33.         ....
  34.       Row({ space: CommonConstants.LOGIN_METHODS_SPACE }) {
  35.         this.imageButton($r('app.media.login_method1'))
  36.         this.imageButton($r('app.media.login_method2'))
  37.         this.imageButton($r('app.media.login_method3'))
  38.       }
  39.     }
  40.     ....
  41.   }
  42. }
复制代码
获取用户输入

当用户登录前,需要获取用户输入的帐号和暗码才气执行登录逻辑。给TextInput设置onChange事故,在onChange事故里面及时获取用户输入的文本信息。
  1. // LoginPage.ets
  2. TextInput({ placeholder: $r('app.string.account') })
  3.   .maxLength(CommonConstants.INPUT_ACCOUNT_LENGTH)
  4.   .type(InputType.Number)
  5.   .inputStyle()
  6.   .onChange((value: string) => {
  7.     this.account = value;
  8.   })
复制代码
控制LoadingProgress表现和隐藏

给登录按钮绑定onClick事故,调用login方法模拟登录。界说变量isShowProgress联合条件渲染if用来控制LoadingProgress的表现和隐藏。当用户点击按钮时设置isShowProgress为true,即表现LoadingProgress;使用定时器setTimeout设置isShowProgress 2秒后为false,即隐藏LoadingProgress,然后执行跳转到首页的逻辑。
  1. // LoginPage.ets
  2. @Entry
  3. @Component
  4. struct LoginPage {
  5.   @State account: string = '';
  6.   @State password: string = '';
  7.   @State isShowProgress: boolean = false;
  8.   private timeOutId = null;
  9.   ...
  10.   login() {
  11.     if (this.account === '' || this.password === '') {
  12.       prompt.showToast({
  13.         message: $r('app.string.input_empty_tips')
  14.       })
  15.     } else {
  16.       this.isShowProgress = true;
  17.       if (this.timeOutId === null) {
  18.         this.timeOutId = setTimeout(() => {
  19.           this.isShowProgress = false;
  20.           this.timeOutId = null;
  21.           router.replaceUrl({ url: 'pages/MainPage' });
  22.         }, CommonConstants.LOGIN_DELAY_TIME);
  23.       }
  24.     }
  25.   }
  26.   ...
  27.   build() {
  28.     Column() {
  29.       ...
  30.       Button($r('app.string.login'), { type: ButtonType.Capsule })
  31.         ....
  32.         .onClick(() => {
  33.           this.login();
  34.         })
  35.       ...
  36.       if (this.isShowProgress) {
  37.         LoadingProgress()
  38.           .color($r('app.color.loading_color'))
  39.           .width($r('app.float.login_progress_size'))
  40.           .height($r('app.float.login_progress_size'))
  41.           .margin({ top: $r('app.float.login_progress_margin_top') })
  42.       }
  43.       ...
  44.     }
  45.     ...
  46.   }
  47. }
复制代码
实现页面跳转

页面间的跳转可以使用router模块相关API来实现,使用前需要先导入该模块,然后使用router.replace()方法实现页面跳转。
  1. // LoginPage.ets
  2. import router from '@ohos.router';
  3. login() {
  4.   if (this.account === '' || this.password === '') {
  5.     ...
  6.   } else {
  7.     this.isShowProgress = true;
  8.     if (this.timeOutId === -1) {
  9.       this.timeOutId = setTimeout(() => {
  10.         this.isShowProgress = false;
  11.         this.timeOutId = -1;
  12.         router.replaceUrl({ url: 'pages/MainPage' });
  13.       }, CommonConstants.LOGIN_DELAY_TIME);
  14.     }
  15.   }
  16. }
复制代码
实现“首页”和“我的”页面

界说资源数据

由于“首页”和“我的”页面中有多处图片和笔墨的组合,因此提取出ItemData类。在MainViewModel.ets文件中对页面使用的资源举行界说,在MainViewModel.ets文件中界说数据。
  1. // ItemData.ets
  2. export default class PageResource {
  3.   title: Resource;
  4.   img?: Resource;
  5.   others?: Resource;
  6.   constructor(title: Resource, img?: Resource, others?: Resource) {
  7.     this.title = title;
  8.     this.img = img;
  9.     this.others = others;
  10.   }
  11. }
  12. // MainViewModel.ets
  13. import ItemData from './temData';
  14. export class MainViewModel {
  15.   ...
  16.   getFirstGridData(): Array<ItemData> {
  17.     let firstGridData: ItemData[] = [
  18.       new ItemData($r('app.string.my_love'), $r('app.media.love')),
  19.       new ItemData($r('app.string.history_record'), $r('app.media.record')),
  20.       ...
  21.     ];
  22.     return firstGridData;
  23.   }
  24.   ...
  25. }
  26. export default new MainViewModel();
复制代码
实现页面框架

从前面先容章节的示意图可以看出,本示例由两个tab页组成,使用Tabs组件来实现,提取tabBar的公共样式,同时设置TabContent和Tabs的backgroundColor来实现底部tabBar栏背景致突出的结果。
  1. // MainPage.ets
  2. Tabs({
  3.   barPosition: BarPosition.End,
  4.   controller: this.tabsController
  5. }) {
  6.   TabContent() {
  7.     ...
  8.   }
  9.   ...
  10.   .backgroundColor($r('app.color.mainPage_backgroundColor')) // “首页”的页面背景色
  11.   .tabBar(this.TabBuilder(CommonConstants.HOME_TITLE, CommonConstants.HOME_TAB_INDEX,
  12.   $r('app.media.home_selected'), $r('app.media.home_normal')))
  13.   ...
  14. }
  15. ...
  16. .backgroundColor(Color.White)  // 底部tabBar栏背景色
  17. ...
  18. .onChange((index: number) => {
  19.   this.currentIndex = index;
  20. })
  21. ...
复制代码
实现“首页”内容

“首页”结果如下所示:

从上面结果如可以看出“首页”由三部分内容组成分别是轮播图、2*4栅格图、4*4栅格图。首先使用Swiper组件实现轮播图,无需设置图片大小。
  1. // Home.ets
  2. Swiper(this.swiperController) {
  3.   ForEach(mainViewModel.getSwiperImages(), (img: Resource) => {
  4.     Image(img).borderRadius($r('app.float.home_swiper_borderRadius'))
  5.   }, (img: Resource) => JSON.stringify(img.id))
  6. }
  7. ...
  8. .autoPlay(true)
  9. ...
复制代码
然后使用Grid组件实现2*4栅格图,代码如下
  1. // Home.ets
  2. Grid() {
  3.   ForEach(mainViewModel.getFirstGridData(), (item: ItemData) => {
  4.     GridItem() {
  5.       Column() {
  6.         Image(item.img)
  7.           .width($r('app.float.home_homeCell_size'))
  8.           .height($r('app.float.home_homeCell_size'))
  9.         Text(item.title)
  10.           .fontSize($r('app.float.little_text_size'))
  11.           .margin({ top: $r('app.float.home_homeCell_margin') })
  12.       }
  13.     }
  14.   }, (item: ItemData) => JSON.stringify(item))
  15. }
  16. .columnsTemplate('1fr 1fr 1fr 1fr')
  17. .rowsTemplate('1fr 1fr')
  18. ...
复制代码
使用Grid组件实现4*4栅格列表栏,其中单个栅格中有一张背景图片和两行字体差别的文本,因此在Column组件中放置两个Text组件,并设置背景图,留意Grid组件必须设置高度,否则大概出现页面空白。
  1. // Home.ets
  2. Grid() {
  3.   ForEach(mainViewModel.getSecondGridData(), (secondItem: ItemData) => {
  4.     GridItem() {
  5.       Column() {
  6.         Text(secondItem.title)
  7.           ...
  8.         Text(secondItem.others)
  9.           ...
  10.       }
  11.       .alignItems(HorizontalAlign.Start)
  12.     }
  13.     ...
  14.     .backgroundImage(secondItem.img)
  15.     .backgroundImageSize(ImageSize.Cover)
  16.     ...
  17.   }, (secondItem: ItemData) => JSON.stringify(secondItem))
  18. }
  19. ...
  20. .height($r('app.float.home_secondGrid_height'))
  21. .columnsTemplate('1fr 1fr')
  22. .rowsTemplate('1fr 1fr')
  23. ...
复制代码
实现“我的”页内容

“我的”页面结果图如下:

使用List组件联合ForEach语句来实现页面列表内容,其中引用了settingCell子组件,列表间的灰色分割线可以使用Divider属性实现,代码实现如下:
  1. // Setting.ets
  2. List() {
  3.   ForEach(mainViewModel.getSettingListData(), (item: ItemData) => {
  4.     ListItem() {
  5.       this.settingCell(item)
  6.     }
  7.     .height($r('app.float.setting_list_height'))
  8.   }, (item: ItemData) => JSON.stringify(item))
  9. }
  10. ...
  11. .divider({  // 设置分隔线
  12.   ...
  13. })
  14. ...
  15. @Builder settingCell(item: ItemData) {
  16.   Row() {
  17.     Row({ space: CommonConstants.COMMON_SPACE }) {
  18.       Image(item.img)
  19.         ...
  20.       Text(item.title)
  21.         ...
  22.     }
  23.     if (item.others === null) {
  24.       Image($r("app.media.right_grey"))
  25.         ...
  26.     } else {
  27.       Toggle({ type: ToggleType.Switch, isOn: false })
  28.     }
  29.   }
  30.   .justifyContent(FlexAlign.SpaceBetween)  // 相邻元素之间距离相同
  31.   ...
  32. }
复制代码
总结

目前你已经乐成完成了Codelab而且学到了:
为了资助各人更深入有效的学习到鸿蒙开发知识点,小编特意给各人准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完备版方式请点击→《HarmonyOS讲授视频
HarmonyOS讲授视频:语法ArkTS、TypeScript、ArkUI等…视频教程




鸿蒙生态应用开发白皮书V2.0PDF:

获取完备版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF

鸿蒙 (Harmony OS)开发学习手册

一、入门必看


二、HarmonyOS 概念

三、如何快速入门?《鸿蒙底子入门学习指南》


四、开发底子知识


五、基于ArkTS 开发


更多相识更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4