0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

HarmonyOS开发案例:【常用组件与布局】

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-05-09 18:20 次阅读

介绍

HarmonyOS ArkUI提供了丰富多样的UI组件,您可以使用这些组件轻松地编写出更加丰富、漂亮的界面。在本篇Codelab中,您将通过一个简单的购物社交应用示例,学习如何使用常用的基础组件和容器组件。

本示例主要包含:“登录”、“首页”、“我的”三个页面,效果图如下:

相关概念

  • [Text]:显示一段文本的组件。
  • [Image]:图片组件,支持本地图片和网络图片的渲染展示。
  • [TextInput]:可以输入单行文本并支持响应输入事件的组件。
  • [Button]:按钮组件,可快速创建不同样式的按钮。
  • [LoadingProgress]:用于显示加载动效的组件。
  • [Flex]:应用弹性方式布局子组件的容器组件。
  • [Column]:沿垂直方向布局的容器。
  • [Row]:沿水平方向布局容器。
  • [List]:列表包含一系列相同宽度的列表项。适合连续、多行呈现同类数据,例如图片和文本。
  • [Swiper]:滑动容器,提供切换子组件显示的能力。
  • [Grid]:网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。

环境搭建

软件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:[润和RK3568开发板]。
  • OpenHarmony系统:3.2 Release。

环境搭建

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

  1. [获取OpenHarmony系统版本]:标准系统解决方案(二进制)。以3.2 Release版本为例:
  2. 搭建烧录环境。
    1. [完成DevEco Device Tool的安装]
    2. [完成RK3568开发板的烧录]
  3. 搭建开发环境。
    1. 开始前请参考[工具准备],完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考[使用工程向导]创建工程(模板选择“Empty Ability”)。
    3. 工程创建完成后,选择使用[真机进行调测]。
    4. 鸿蒙开发指导文档:[qr23.cn/FBD4cY]

代码结构解读

本篇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        // 应用资源目录

`HarmonyOSOpenHarmony鸿蒙文档籽料:mau123789v直接拿`

搜狗高速浏览器截图20240326151547.png

实现“登录”页面

本节主要介绍“登录”页面的实现,效果图如下:

界面使用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;
  })

控制LoadingProgress显示和隐藏

给登录按钮绑定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;
})
...

实现“首页”内容

“首页”效果如下所示:

从上面效果如可以看出“首页”由三部分内容组成分别是轮播图、24栅格图、44栅格图。首先使用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)  // 相邻元素之间距离相同
  ...
}

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 开发板
    +关注

    关注

    25

    文章

    4546

    浏览量

    94743
  • 组件
    +关注

    关注

    1

    文章

    361

    浏览量

    17634
  • 鸿蒙
    +关注

    关注

    55

    文章

    1875

    浏览量

    42181
  • HarmonyOS
    +关注

    关注

    79

    文章

    1910

    浏览量

    29401
  • OpenHarmony
    +关注

    关注

    24

    文章

    3436

    浏览量

    15250
收藏 人收藏

    评论

    相关推荐

    HarmonyOS开发案例:【 slider组件的使用】

    主要介绍slider滑动条组件的使用。如图所示拖动对应滑动条调节风车的旋转速度以及缩放比例。
    的头像 发表于 04-25 22:02 611次阅读
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发案</b>例:【 slider<b class='flag-5'>组件</b>的使用】

    HarmonyOS开发案例:【image、image-animator组件

    OpenHarmony提供了常用的图片、图片帧动画播放器组件开发者可以根据实际场景和开发需求,实现不同的界面交互效果,包括:点击阴影效果、点击切换状态、点击动画效果、点击切换动效。
    的头像 发表于 04-26 17:32 753次阅读
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发案</b>例:【image、image-animator<b class='flag-5'>组件</b>】

    HarmonyOS开发案例:【使用List组件实现商品列表】

    OpenHarmony ArkTS提供了丰富的接口和组件开发者可以根据实际场景和开发需求,选用不同的组件和接口。
    的头像 发表于 05-10 16:41 488次阅读
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发案</b>例:【使用List<b class='flag-5'>组件</b>实现商品列表】

    HarmonyOS开发案例:【Web组件实现抽奖】

    基于ArkTS的声明式开发范式的样例,主要介绍了Web组件如何加载本地和云端H5小程序。
    的头像 发表于 05-09 18:31 909次阅读
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发案</b>例:【Web<b class='flag-5'>组件</b>实现抽奖】

    HarmonyOS开发案例:【基础组件Slider的使用】

    学习如何使用声明式UI编程框架的基础组件。本篇Codelab将会使用Image组件、Slider组件、Text组件共同实现一个可调节的风车动画
    的头像 发表于 05-10 16:01 423次阅读
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发案</b>例:【基础<b class='flag-5'>组件</b>Slider的使用】

    HarmonyOS IoT 硬件开发案例分享

    ``许思维老师HiSpark Wi-Fi IoT 开发案例分享:案例一:AHT20温湿度传感器开发、调试;案例二:oled屏驱动库移植,调试;案例三:用OLED屏播放视频,Wi-Fi 和 TCP/IP 综合应用。 ``
    发表于 10-27 17:30

    Linux应用开发手册之Python开发案

    本文档涉及的开发案例位于产品资料“4-软件资料\Demo\”路径下的base-demos和python-demos目录。base-demos目录存放Linux常用开发案例,案例bin目录存放
    发表于 05-11 10:21

    #HarmonyOS征文# — HarmonyOS组件布局和事件三者的关系

    事件、双击事件、长按事件、滑动事件等组件布局都会用到事件【本文正在参与“有奖征文 | HarmonyOS征文大赛”活动】https://bbs.elecfans.com/jishu_2098584_1_1.html
    发表于 07-21 11:55

    HarmonyOS实战—布局组件的概述

    输入的文本框组件。3. 布局组件 布局其实也是一种比较特殊的组件。【本文正在参与“有奖征文 | Har
    发表于 08-12 12:23

    基于HarmonyOS Java UI,实现常见组件或者布局

    1. 介绍 本篇Codelab目的本篇Codelab旨在让开发者了解HarmonyOS应用开发常用布局常用
    发表于 10-09 14:13

    HarmonyOS应用开发资料(Svg组件

    1、HarmonyOS应用开发-Svg组件circle  该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。2、
    发表于 03-17 14:49

    HarmonyOS应用开发-ClickableImageJsDome体验

    说明:提供了常用布局组件等页面元素,并且为这些组件提供了很多属性与可监听到的事件(例如动画属性与点击、触碰事件),开发者可以根据实际场景
    发表于 06-18 11:42

    许思维老师HarmonyOS IoT硬件开发案例分享

    许思维老师HiSpark Wi-Fi IoT 开发案例分享:案例一:AHT20温湿度传感器开发、调试;案例二:oled屏驱动库移植,调试;案例三:用OLED屏播放视频,Wi-Fi 和 TCP/IP 综合应用。
    发表于 10-29 10:39 39次下载
    许思维老师<b class='flag-5'>HarmonyOS</b> IoT硬件<b class='flag-5'>开发案</b>例分享

    华为开发者分论坛HarmonyOS学生公开课-OpenHarmony Codelabs开发案

    2021华为开发者分论坛HarmonyOS学生公开课-OpenHarmony Codelabs开发案
    的头像 发表于 10-24 11:25 1652次阅读
    华为<b class='flag-5'>开发</b>者分论坛<b class='flag-5'>HarmonyOS</b>学生公开课-OpenHarmony Codelabs<b class='flag-5'>开发案</b>例

    HarmonyOS开发案例:【 switch、chart组件的使用】

    基于switch组件和chart组件,实现线形图、占比图、柱状图,并通过switch切换chart组件数据的动静态显示。
    的头像 发表于 04-25 20:58 147次阅读
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发案</b>例:【 switch、chart<b class='flag-5'>组件</b>的使用】