0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

HarmonyOS開發(fā)案例:【常用組件與布局】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-05-09 18:20 ? 次閱讀

介紹

HarmonyOS ArkUI提供了豐富多樣的UI組件,您可以使用這些組件輕松地編寫出更加豐富、漂亮的界面。在本篇Codelab中,您將通過一個(gè)簡單的購物社交應(yīng)用示例,學(xué)習(xí)如何使用常用的基礎(chǔ)組件和容器組件。

本示例主要包含:“登錄”、“首頁”、“我的”三個(gè)頁面,效果圖如下:

相關(guān)概念

  • [Text]:顯示一段文本的組件。
  • [Image]:圖片組件,支持本地圖片和網(wǎng)絡(luò)圖片的渲染展示。
  • [TextInput]:可以輸入單行文本并支持響應(yīng)輸入事件的組件。
  • [Button]:按鈕組件,可快速創(chuàng)建不同樣式的按鈕。
  • [LoadingProgress]:用于顯示加載動效的組件。
  • [Flex]:應(yīng)用彈性方式布局子組件的容器組件。
  • [Column]:沿垂直方向布局的容器。
  • [Row]:沿水平方向布局容器。
  • [List]:列表包含一系列相同寬度的列表項(xiàng)。適合連續(xù)、多行呈現(xiàn)同類數(shù)據(jù),例如圖片和文本。
  • [Swiper]:滑動容器,提供切換子組件顯示的能力。
  • [Grid]:網(wǎng)格容器,由“行”和“列”分割的單元格所組成,通過指定“項(xiàng)目”所在的單元格做出各種各樣的布局。

環(huán)境搭建

軟件要求

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

硬件要求

  • 開發(fā)板類型:[潤和RK3568開發(fā)板]。
  • OpenHarmony系統(tǒng):3.2 Release。

環(huán)境搭建

我們首先要完成開發(fā)環(huán)境的搭建,本示例以RK3568開發(fā)板為例,參照以下步驟進(jìn)行:

  1. [獲取OpenHarmony系統(tǒng)版本]:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。以3.2 Release版本為例:
  2. 搭建燒錄環(huán)境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開發(fā)板的燒錄]
  3. 搭建開發(fā)環(huán)境。
    1. 開始前請參考[工具準(zhǔn)備],完成DevEco Studio的安裝和開發(fā)環(huán)境配置。
    2. 開發(fā)環(huán)境配置完成后,請參考[使用工程向?qū)創(chuàng)建工程(模板選擇“Empty Ability”)。
    3. 工程創(chuàng)建完成后,選擇使用[真機(jī)進(jìn)行調(diào)測]。
    4. 鴻蒙開發(fā)指導(dǎo)文檔:[qr23.cn/FBD4cY]

代碼結(jié)構(gòu)解讀

本篇Codelab只對核心代碼進(jìn)行講解,對于完整代碼,我們會在附件下載和gitee源碼中提供下載方式。

├──entry/src/main/ets              // 代碼區(qū)
│  ├──common
│  │  └──constants
│  │     └──CommonConstants.ets    // 公共常量類
│  ├──entryability
│  │  └──EntryAbility.ts           // 程序入口類
│  ├──pages
│  │  ├──LoginPage.ets             // 登錄界面
│  │  └──MainPage.ets	           // 主界面	
│  ├──view
│  │  ├──Home.ets                  // 首頁
│  │  └──Setting.ets               // 設(shè)置頁
│  └──viewmodel
│     ├──ItemData.ets              // 列表數(shù)據(jù)實(shí)體類
│     └──MainViewModel.ets         // 主界面視圖Model
└──entry/src/main/resources        // 應(yīng)用資源目錄

`HarmonyOSOpenHarmony鴻蒙文檔籽料:mau123789v直接拿`

搜狗高速瀏覽器截圖20240326151547.png

實(shí)現(xiàn)“登錄”頁面

本節(jié)主要介紹“登錄”頁面的實(shí)現(xiàn),效果圖如下:

界面使用Column容器組件布局,由Image、Text、TextInput、Button、LoadingProgress等基礎(chǔ)組件構(gòu)成,主要代碼如下:

// 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'))
      }
    }
    ....
  }
}

獲取用戶輸入

當(dāng)用戶登錄前,需要獲取用戶輸入的帳號和密碼才能執(zhí)行登錄邏輯。給TextInput設(shè)置onChange事件,在onChange事件里面實(shí)時(shí)獲取用戶輸入的文本信息。

// 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事件,調(diào)用login方法模擬登錄。定義變量isShowProgress結(jié)合條件渲染if用來控制LoadingProgress的顯示和隱藏。當(dāng)用戶點(diǎn)擊按鈕時(shí)設(shè)置isShowProgress為true,即顯示LoadingProgress;使用定時(shí)器setTimeout設(shè)置isShowProgress 2秒后為false,即隱藏LoadingProgress,然后執(zhí)行跳轉(zhuǎn)到首頁的邏輯。

// 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') })
      }

      ...
    }
    ...
  }
}

實(shí)現(xiàn)頁面跳轉(zhuǎn)

頁面間的跳轉(zhuǎn)可以使用router模塊相關(guān)API來實(shí)現(xiàn),使用前需要先導(dǎo)入該模塊,然后使用router.replace()方法實(shí)現(xiàn)頁面跳轉(zhuǎn)。

// 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);
    }
  }
}

實(shí)現(xiàn)“首頁”和“我的”頁面

定義資源數(shù)據(jù)

由于“首頁”和“我的”頁面中有多處圖片和文字的組合,因此提取出ItemData類。在MainViewModel.ets文件中對頁面使用的資源進(jìn)行定義,在MainViewModel.ets文件中定義數(shù)據(jù)。

// 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();

實(shí)現(xiàn)頁面框架

從前面介紹章節(jié)的示意圖可以看出,本示例由兩個(gè)tab頁組成,使用Tabs組件來實(shí)現(xiàn),提取tabBar的公共樣式,同時(shí)設(shè)置TabContent和Tabs的backgroundColor來實(shí)現(xiàn)底部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;
})
...

實(shí)現(xiàn)“首頁”內(nèi)容

“首頁”效果如下所示:

從上面效果如可以看出“首頁”由三部分內(nèi)容組成分別是輪播圖、24柵格圖、44柵格圖。首先使用Swiper組件實(shí)現(xiàn)輪播圖,無需設(shè)置圖片大小。

// 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組件實(shí)現(xiàn)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組件實(shí)現(xiàn)4*4柵格列表欄,其中單個(gè)柵格中有一張背景圖片和兩行字體不同的文本,因此在Column組件中放置兩個(gè)Text組件,并設(shè)置背景圖,注意Grid組件必須設(shè)置高度,否則可能出現(xiàn)頁面空白。

// 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')
...

實(shí)現(xiàn)“我的”頁內(nèi)容

“我的”頁面效果圖如下:

使用List組件結(jié)合ForEach語句來實(shí)現(xiàn)頁面列表內(nèi)容,其中引用了settingCell子組件,列表間的灰色分割線可以使用Divider屬性實(shí)現(xiàn),代碼實(shí)現(xiàn)如下:

// 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({  // 設(shè)置分隔線
  ...
})
...

@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)  // 相鄰元素之間距離相同
  ...
}

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 開發(fā)板
    +關(guān)注

    關(guān)注

    25

    文章

    4834

    瀏覽量

    96827
  • 組件
    +關(guān)注

    關(guān)注

    1

    文章

    498

    瀏覽量

    17771
  • 鴻蒙
    +關(guān)注

    關(guān)注

    57

    文章

    2287

    瀏覽量

    42629
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1954

    瀏覽量

    29897
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3607

    瀏覽量

    15958
收藏 人收藏

    評論

    相關(guān)推薦

    HarmonyOS開發(fā)案例:【 slider組件的使用】

    主要介紹slider滑動條組件的使用。如圖所示拖動對應(yīng)滑動條調(diào)節(jié)風(fēng)車的旋轉(zhuǎn)速度以及縮放比例。
    的頭像 發(fā)表于 04-25 22:02 ?823次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【 slider<b class='flag-5'>組件</b>的使用】

    HarmonyOS開發(fā)案例:【image、image-animator組件

    OpenHarmony提供了常用的圖片、圖片幀動畫播放器組件,開發(fā)者可以根據(jù)實(shí)際場景和開發(fā)需求,實(shí)現(xiàn)不同的界面交互效果,包括:點(diǎn)擊陰影效果、點(diǎn)擊切換狀態(tài)、點(diǎn)擊動畫效果、點(diǎn)擊切換動效。
    的頭像 發(fā)表于 04-26 17:32 ?1321次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【image、image-animator<b class='flag-5'>組件</b>】

    HarmonyOS開發(fā)案例:【使用List組件實(shí)現(xiàn)商品列表】

    OpenHarmony ArkTS提供了豐富的接口和組件,開發(fā)者可以根據(jù)實(shí)際場景和開發(fā)需求,選用不同的組件和接口。
    的頭像 發(fā)表于 05-10 16:41 ?1166次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【使用List<b class='flag-5'>組件</b>實(shí)現(xiàn)商品列表】

    HarmonyOS開發(fā)案例:【W(wǎng)eb組件實(shí)現(xiàn)抽獎】

    基于ArkTS的聲明式開發(fā)范式的樣例,主要介紹了Web組件如何加載本地和云端H5小程序。
    的頭像 發(fā)表于 05-09 18:31 ?1264次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【W(wǎng)eb<b class='flag-5'>組件</b>實(shí)現(xiàn)抽獎】

    HarmonyOS開發(fā)案例:【基礎(chǔ)組件Slider的使用】

    學(xué)習(xí)如何使用聲明式UI編程框架的基礎(chǔ)組件。本篇Codelab將會使用Image組件、Slider組件、Text組件共同實(shí)現(xiàn)一個(gè)可調(diào)節(jié)的風(fēng)車動畫
    的頭像 發(fā)表于 05-10 16:01 ?608次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【基礎(chǔ)<b class='flag-5'>組件</b>Slider的使用】

    HarmonyOS開發(fā)ArkUI案例:【常用布局容器對齊方式】

    基于ArkTS擴(kuò)展的聲明式開發(fā)范式,實(shí)現(xiàn)Flex、Column、Row和Stack四種常用布局容器對齊方式。
    的頭像 發(fā)表于 05-08 16:47 ?1409次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)</b>ArkUI案例:【<b class='flag-5'>常用布局</b>容器對齊方式】

    Linux應(yīng)用開發(fā)手冊之Python開發(fā)案

    本文檔涉及的開發(fā)案例位于產(chǎn)品資料“4-軟件資料\Demo\”路徑下的base-demos和python-demos目錄。base-demos目錄存放Linux常用開發(fā)案例,案例bin目錄存放
    發(fā)表于 05-11 10:21

    #HarmonyOS征文# — HarmonyOS組件布局和事件三者的關(guān)系

    事件、雙擊事件、長按事件、滑動事件等組件布局都會用到事件【本文正在參與“有獎?wù)魑?| HarmonyOS征文大賽”活動】https://bbs.elecfans.com/jishu_2098584_1_1.html
    發(fā)表于 07-21 11:55

    HarmonyOS實(shí)戰(zhàn)—布局組件的概述

    輸入的文本框組件。3. 布局組件 布局其實(shí)也是一種比較特殊的組件。【本文正在參與“有獎?wù)魑?| Har
    發(fā)表于 08-12 12:23

    基于HarmonyOS Java UI,實(shí)現(xiàn)常見組件或者布局

    1. 介紹 本篇Codelab目的本篇Codelab旨在讓開發(fā)者了解HarmonyOS應(yīng)用開發(fā)常用布局常用
    發(fā)表于 10-09 14:13

    HarmonyOS應(yīng)用開發(fā)資料(Svg組件

    1、HarmonyOS應(yīng)用開發(fā)-Svg組件circle  該組件從API version 7開始支持。后續(xù)版本如有新增內(nèi)容,則采用上角標(biāo)單獨(dú)標(biāo)記該內(nèi)容的起始版本。2、
    發(fā)表于 03-17 14:49

    HarmonyOS應(yīng)用開發(fā)-ClickableImageJsDome體驗(yàn)

    說明:提供了常用布局、組件等頁面元素,并且為這些組件提供了很多屬性與可監(jiān)聽到的事件(例如動畫屬性與點(diǎn)擊、觸碰事件),開發(fā)者可以根據(jù)實(shí)際場景
    發(fā)表于 06-18 11:42

    華為開發(fā)者分論壇HarmonyOS學(xué)生公開課-OpenHarmony Codelabs開發(fā)案

    2021華為開發(fā)者分論壇HarmonyOS學(xué)生公開課-OpenHarmony Codelabs開發(fā)案
    的頭像 發(fā)表于 10-24 11:25 ?1852次閱讀
    華為<b class='flag-5'>開發(fā)</b>者分論壇<b class='flag-5'>HarmonyOS</b>學(xué)生公開課-OpenHarmony Codelabs<b class='flag-5'>開發(fā)案</b>例

    HarmonyOS 應(yīng)用開發(fā)-ClickableImageJsDome體驗(yàn)

    說明:提供了常用布局組件等頁面元素,并且為這些組件提供了很多屬性與可監(jiān)聽到的事件(例如動畫屬性與點(diǎn)擊、觸碰事件),開發(fā)者可以根據(jù)實(shí)際場景
    的頭像 發(fā)表于 06-20 00:24 ?1065次閱讀
    <b class='flag-5'>HarmonyOS</b> 應(yīng)用<b class='flag-5'>開發(fā)</b>-ClickableImageJsDome體驗(yàn)

    HarmonyOS開發(fā)案例:【 switch、chart組件的使用】

    基于switch組件和chart組件,實(shí)現(xiàn)線形圖、占比圖、柱狀圖,并通過switch切換chart組件數(shù)據(jù)的動靜態(tài)顯示。
    的頭像 發(fā)表于 04-25 20:58 ?469次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【 switch、chart<b class='flag-5'>組件</b>的使用】