赞
踩
HarmonyOS ArkUI提供了丰富多样的UI组件,您可以使用这些组件轻松地编写出更加丰富、漂亮的界面。在本篇文章中,您将通过一个简单的购物社交应用示例,学习如何使用常用的基础组件和容器组件。
本示例主要包含:“登录”、“首页”、“我的”三个页面,效果图如下:
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:
获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:
搭建烧录环境。
本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在附件下载和gitee源码中提供下载方式。
- ├──entry/src/main/ets // 代码区
- │ ├──common
- │ │ └──constants
- │ │ └──CommonConstants.ets // 公共常量类
- │ ├──entryability
- │ │ └──EntryAbility.ts // 程序入口类
- │ ├──pages
- │ │ ├──LoginPage.ets // 登录界面
- │ │ └──MainPage.ets // 主界面
- │ ├──view
- │ │ ├──Home.ets // 首页
- │ │ └──Setting.ets // 设置页
- │ └──viewmodel
- │ ├──ItemData.ets // 列表数据实体类
- │ └──MainViewModel.ets // 主界面视图Model
- └──entry/src/main/resources // 应用资源目录
本节主要介绍“登录”页面的实现,效果图如下:
界面使用Column容器组件布局,由Image、Text、TextInput、Button、LoadingProgress等基础组件构成,主要代码如下:
- // LoginPage.ets
- @Entry
- @Component
- struct LoginPage {
- ...
- build() {
- Column() {
- Image($r('app.media.logo'))
- ...
- Text($r('app.string.login_page'))
- ...
- Text($r('app.string.login_more'))
- ...
-
- TextInput({ placeholder: $r('app.string.account') })
- ...
-
- TextInput({ placeholder: $r('app.string.password') })
- ...
-
- Row() {
- Text($r('app.string.message_login')).blueTextStyle()
- Text($r('app.string.forgot_password')).blueTextStyle()
- }
- ....
-
- Button($r('app.string.login'), { type: ButtonType.Capsule })
- ....
- Text($r('app.string.register_account'))
- ....
-
- if (this.isShowProgress) {
- LoadingProgress()
- ....
- }
-
- Blank()
- Text($r('app.string.other_login_method'))
- ....
- Row({ space: CommonConstants.LOGIN_METHODS_SPACE }) {
- this.imageButton($r('app.media.login_method1'))
- this.imageButton($r('app.media.login_method2'))
- this.imageButton($r('app.media.login_method3'))
- }
- }
- ....
- }
- }
当用户登录前,需要获取用户输入的帐号和密码才能执行登录逻辑。给TextInput设置onChange事件,在onChange事件里面实时获取用户输入的文本信息。
- // LoginPage.ets
- TextInput({ placeholder: $r('app.string.account') })
- .maxLength(CommonConstants.INPUT_ACCOUNT_LENGTH)
- .type(InputType.Number)
- .inputStyle()
- .onChange((value: string) => {
- this.account = value;
- })
给登录按钮绑定onClick事件,调用login方法模拟登录。定义变量isShowProgress结合条件渲染if用来控制LoadingProgress的显示和隐藏。当用户点击按钮时设置isShowProgress为true,即显示LoadingProgress;使用定时器setTimeout设置isShowProgress 2秒后为false,即隐藏LoadingProgress,然后执行跳转到首页的逻辑。
- // LoginPage.ets
- @Entry
- @Component
- struct LoginPage {
- @State account: string = '';
- @State password: string = '';
- @State isShowProgress: boolean = false;
- private timeOutId = null;
-
- ...
-
- login() {
- if (this.account === '' || this.password === '') {
- prompt.showToast({
- message: $r('app.string.input_empty_tips')
- })
- } else {
- this.isShowProgress = true;
- if (this.timeOutId === null) {
- this.timeOutId = setTimeout(() => {
- this.isShowProgress = false;
- this.timeOutId = null;
- router.replaceUrl({ url: 'pages/MainPage' });
- }, CommonConstants.LOGIN_DELAY_TIME);
- }
- }
- }
-
- ...
-
- build() {
- Column() {
- ...
-
- Button($r('app.string.login'), { type: ButtonType.Capsule })
- ....
- .onClick(() => {
- this.login();
- })
- ...
-
- if (this.isShowProgress) {
- LoadingProgress()
- .color($r('app.color.loading_color'))
- .width($r('app.float.login_progress_size'))
- .height($r('app.float.login_progress_size'))
- .margin({ top: $r('app.float.login_progress_margin_top') })
- }
-
- ...
- }
- ...
- }
- }
页面间的跳转可以使用router模块相关API来实现,使用前需要先导入该模块,然后使用router.replace()方法实现页面跳转。
- // LoginPage.ets
- import router from '@ohos.router';
-
- login() {
- if (this.account === '' || this.password === '') {
- ...
- } else {
- this.isShowProgress = true;
- if (this.timeOutId === -1) {
- this.timeOutId = setTimeout(() => {
- this.isShowProgress = false;
- this.timeOutId = -1;
- router.replaceUrl({ url: 'pages/MainPage' });
- }, CommonConstants.LOGIN_DELAY_TIME);
- }
- }
- }
由于“首页”和“我的”页面中有多处图片和文字的组合,因此提取出ItemData类。在MainViewModel.ets文件中对页面使用的资源进行定义,在MainViewModel.ets文件中定义数据。
- // ItemData.ets
- export default class PageResource {
- title: Resource;
- img?: Resource;
- others?: Resource;
- constructor(title: Resource, img?: Resource, others?: Resource) {
- this.title = title;
- this.img = img;
- this.others = others;
- }
- }
-
- // MainViewModel.ets
- import ItemData from './temData';
- export class MainViewModel {
- ...
- getFirstGridData(): Array<ItemData> {
- let firstGridData: ItemData[] = [
- new ItemData($r('app.string.my_love'), $r('app.media.love')),
- new ItemData($r('app.string.history_record'), $r('app.media.record')),
- ...
- ];
- return firstGridData;
- }
- ...
- }
- export default new MainViewModel();
从前面介绍章节的示意图可以看出,本示例由两个tab页组成,使用Tabs组件来实现,提取tabBar的公共样式,同时设置TabContent和Tabs的backgroundColor来实现底部tabBar栏背景色突出的效果。
- // MainPage.ets
- Tabs({
- barPosition: BarPosition.End,
- controller: this.tabsController
- }) {
- TabContent() {
- ...
- }
- ...
- .backgroundColor($r('app.color.mainPage_backgroundColor')) // “首页”的页面背景色
- .tabBar(this.TabBuilder(CommonConstants.HOME_TITLE, CommonConstants.HOME_TAB_INDEX,
- $r('app.media.home_selected'), $r('app.media.home_normal')))
- ...
- }
- ...
- .backgroundColor(Color.White) // 底部tabBar栏背景色
- ...
- .onChange((index: number) => {
- this.currentIndex = index;
- })
- ...
“首页”效果如下所示:
从上面效果如可以看出“首页”由三部分内容组成分别是轮播图、2*4栅格图、4*4栅格图。首先使用Swiper组件实现轮播图,无需设置图片大小。
- // Home.ets
- Swiper(this.swiperController) {
- ForEach(mainViewModel.getSwiperImages(), (img: Resource) => {
- Image(img).borderRadius($r('app.float.home_swiper_borderRadius'))
- }, (img: Resource) => JSON.stringify(img.id))
- }
- ...
- .autoPlay(true)
- ...
然后使用Grid组件实现2*4栅格图,代码如下
- // Home.ets
- Grid() {
- ForEach(mainViewModel.getFirstGridData(), (item: ItemData) => {
- GridItem() {
- Column() {
- Image(item.img)
- .width($r('app.float.home_homeCell_size'))
- .height($r('app.float.home_homeCell_size'))
- Text(item.title)
- .fontSize($r('app.float.little_text_size'))
- .margin({ top: $r('app.float.home_homeCell_margin') })
- }
- }
- }, (item: ItemData) => JSON.stringify(item))
- }
- .columnsTemplate('1fr 1fr 1fr 1fr')
- .rowsTemplate('1fr 1fr')
- ...
使用Grid组件实现4*4栅格列表栏,其中单个栅格中有一张背景图片和两行字体不同的文本,因此在Column组件中放置两个Text组件,并设置背景图,注意Grid组件必须设置高度,否则可能出现页面空白。
- // Home.ets
- Grid() {
- ForEach(mainViewModel.getSecondGridData(), (secondItem: ItemData) => {
- GridItem() {
- Column() {
- Text(secondItem.title)
- ...
- Text(secondItem.others)
- ...
- }
- .alignItems(HorizontalAlign.Start)
- }
- ...
- .backgroundImage(secondItem.img)
- .backgroundImageSize(ImageSize.Cover)
- ...
- }, (secondItem: ItemData) => JSON.stringify(secondItem))
- }
- ...
- .height($r('app.float.home_secondGrid_height'))
- .columnsTemplate('1fr 1fr')
- .rowsTemplate('1fr 1fr')
- ...
“我的”页面效果图如下:
使用List组件结合ForEach语句来实现页面列表内容,其中引用了settingCell子组件,列表间的灰色分割线可以使用Divider属性实现,代码实现如下:
- // Setting.ets
- List() {
- ForEach(mainViewModel.getSettingListData(), (item: ItemData) => {
- ListItem() {
- this.settingCell(item)
- }
- .height($r('app.float.setting_list_height'))
- }, (item: ItemData) => JSON.stringify(item))
- }
- ...
- .divider({ // 设置分隔线
- ...
- })
- ...
-
- @Builder settingCell(item: ItemData) {
- Row() {
- Row({ space: CommonConstants.COMMON_SPACE }) {
- Image(item.img)
- ...
- Text(item.title)
- ...
- }
- if (item.others === null) {
- Image($r("app.media.right_grey"))
- ...
- } else {
- Toggle({ type: ToggleType.Switch, isOn: false })
- }
- }
- .justifyContent(FlexAlign.SpaceBetween) // 相邻元素之间距离相同
- ...
- }
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员,可以直接领取这份资料
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
HarmonOS基础技能
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
OpenHarmony北向、南向开发环境搭建
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。