通過(guò)電競(jìng)快覽應(yīng)用學(xué)ArkUI
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
為了能夠進(jìn)一步對(duì)OpenHarmony3.0內(nèi)置應(yīng)用做修改,我需要先掌握ArkUI聲明式開發(fā)范式的相關(guān)知識(shí)。通過(guò)電競(jìng)快覽應(yīng)用示例能夠快速學(xué)習(xí)ArkUI聲明式開發(fā),并對(duì)相關(guān)知識(shí)點(diǎn)進(jìn)行擴(kuò)展學(xué)習(xí),最終達(dá)到對(duì)組件、布局、動(dòng)效和數(shù)據(jù)狀態(tài)管理的初步掌握,并將最終的健康飲食應(yīng)用程序安裝到燒錄了OpenHarmony3.0的Hi3516開發(fā)板上。
ArkUI是一套構(gòu)建HarmonyOS應(yīng)用界面的聲明式UI開發(fā)框架。它使用極簡(jiǎn)的UI信息語(yǔ)法、豐富的UI組件、以及實(shí)時(shí)預(yù)覽工具,幫助您提升HarmonyOS應(yīng)用界面開發(fā)效率30%。您只需使用一套TS/JS API,就能在多個(gè)HarmonyOS設(shè)備上提供生動(dòng)而流出的用戶界面體驗(yàn)。 ——引自HarmonyOS應(yīng)用開發(fā)官網(wǎng)
準(zhǔn)備
- DevEco Studio 3.0 Beta1
- OpenHarmony SDK 3.0
- 數(shù)據(jù)來(lái)源于天行數(shù)據(jù)API
通過(guò)電競(jìng)快覽應(yīng)用學(xué)ArkUI
1. 創(chuàng)建電競(jìng)快覽應(yīng)用(OpenHarmony版)
配置OpenHarmony SDK
打開DevEco Studio,點(diǎn)擊左下角Configure,選擇Setting進(jìn)入設(shè)置界面。在SDK Manager菜單下選擇OpenHarmony SDK,自定義存放路徑,并勾選安裝Platforms下的SDK及Tools下的Previewer和Toolchains。


點(diǎn)擊Create Project創(chuàng)建項(xiàng)目
在Choose Your Ability Template界面下拉到最底部,選擇[Standard]Empty Ability模板

配置工程界面完善項(xiàng)目信息

Project name:項(xiàng)目名稱
Project type:項(xiàng)目類型
Bundle name:包名稱
Save location:項(xiàng)目保存地址
Language:選擇編程語(yǔ)言(eTS)
Compatible API version:選擇兼容版本(API Version 7)
Device type:設(shè)備類型(Phone)
點(diǎn)擊Finish,等待項(xiàng)目構(gòu)建完成。
目錄結(jié)構(gòu)說(shuō)明

app.ets 全局應(yīng)用邏輯和應(yīng)用生命周期管理。
pages 存放所有組件頁(yè)面。
common 存放公共代碼(可選)。
resources 存放資源配置文件。
刪除config.json文件中js -> pages標(biāo)簽下的pages/second
刪除index.ets文件中的一些代碼,如圖所示:

刪除second.ets文件
2. 術(shù)語(yǔ)
認(rèn)識(shí)@Entry
用@Entry裝飾的自定義組件用作頁(yè)面的默認(rèn)入口組件,加載頁(yè)面時(shí),將首先創(chuàng)建并呈現(xiàn)@Entry裝飾的自定義組件。單個(gè)源文件中,可以存在多個(gè)自定義組件,但最多可以使用@Entry裝飾一個(gè)自定義組件。
認(rèn)識(shí)@Component
在聲明式UI中,所有的頁(yè)面都是由組件構(gòu)成。使用@Component裝飾的struct表示該結(jié)構(gòu)體具有組件化能力,能夠成為一個(gè)獨(dú)立的組件,這種類型的組件也稱為自定義組件。
build函數(shù)
build函數(shù)用于定義組件的聲明式UI描述。
認(rèn)識(shí)@Builder
@Builder裝飾器定義了一個(gè)如何渲染自定義組件的方法。通過(guò)其可以在一個(gè)自定義組件內(nèi)快速生成多個(gè)布局內(nèi)容。比如要在一個(gè)頁(yè)面顯示多個(gè)名稱,使用多個(gè)Text組件顯得代碼臃腫且冗余,使用@Builder定義一個(gè)公用的方法,在組件中引入,代碼量少且達(dá)到了復(fù)用。
3. 構(gòu)建電競(jìng)新聞列表

由圖可知,整個(gè)界面分為上下兩部分,上部分顯示標(biāo)題欄,下部分顯示電競(jìng)新聞列表。
頁(yè)面中使用的組件
1)Column組件
Column組件是容器組件,是沿垂直方向布局的容器。相對(duì)的就存在沿水平方向布局的容器,其為Row組件,這兩個(gè)組件我將它們定位為線性布局容器。
可以通過(guò)alignItems屬性來(lái)設(shè)置子組件在水平方向上的對(duì)齊格式。提供了Start、Center、End三種對(duì)齊方式。
- Column() {
- //子組件
- }
- .alignItems(HorizontalAlign.Center)
2)Flex組件
Flex是彈性布局組件,其提供五個(gè)屬性來(lái)控制子組件的顯示方式。
- Flex({direction: FlexDirection.Row,wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Stretch, alginContent: FlexAlign.Start})
direction:描述子組件在Flex容器上排列的方向,即主軸方向,也就是子組件是以橫向排列還是縱向排列。
FlexDirection.Row:橫向(行方向)排列,從行起始位置開始。
FlexDirection.RowReverse:橫向(行方向)排列,與Row方向相反,即從行尾開始排列。
FlexDirection.Column:縱向(列方向)排列,從列起始位置開始。
FlexDirection.ColumnReverse:縱向(列方向)排列,與Column方向相反,即從列尾開始排列。
- Flex({direction: FlexDirection.Row}) {}
- Flex({direction: FlexDirection.RowReverse}) {}
- Flex({direction: FlexDirection.Column}) {}
- Flex({direction: FlexDirection.ColumnReverse}) {}

wrap: Flex容器中子組件是單行/列還是多行/列排列。
justifyContent:子組件在Flex容器主軸上的對(duì)齊格式。
alignItems:子組件在Flex容器交叉軸上的對(duì)齊格式。
alignContent:交叉軸中有額外的空間時(shí),多行內(nèi)容的對(duì)齊方式。僅在wrap為Wrap或WrapReverse下生效。
3)List組件
List組件用于顯示一系列相同寬度的列表項(xiàng),比如顯示新聞列表、商品列表等。List組件和ListItem組件一起使用。ListItem用于展示具體的數(shù)據(jù)項(xiàng)。
- List() {
- ListItem() {
- //組合數(shù)據(jù)項(xiàng)
- }
- ListItem() {
- //組合數(shù)據(jù)項(xiàng)
- }
- }
4)Text組件
Text用于呈現(xiàn)一段信息。
- Text(){}
5)Image組件
Image組件用于渲染展示圖片。
- Image(){}
通用組件屬性和事件
width():設(shè)置組件自身的寬度。
height():設(shè)置組件自身的高度。
margin():設(shè)置外邊距屬性。
padding():設(shè)置內(nèi)邊距屬性。
backgroundColor:設(shè)置組件的背景色。
borderRadius:設(shè)置元素的邊框圓角半徑。
和搭積木一樣,把需要的組件組裝到一起,完成列表頁(yè)的構(gòu)建。
- import router from '@system.router';
- import {ESports} from '../model/ESports.ets';
- import {initOnStartup} from '../model/ESportsList.ets';
- @Component
- struct ESportsListItem {
- private eSportsItem: ESports
- build() {
- Flex({justifyContent:FlexAlign.Start, alignItems: ItemAlign.Center}) {
- Image(this.eSportsItem.picUrl)
- .objectFit(ImageFit.Contain)
- .height('100%')
- .width(120)
- .margin({right: 16, left: 16})
- Column() {
- Text(this.eSportsItem.title)
- .fontSize(14)
- .fontWeight(FontWeight.Bold)
- .maxLines(1)
- .textOverflow({overflow: TextOverflow.Ellipsis})
- Text(this.eSportsItem.description)
- .fontSize(12)
- .fontColor('#cccccc')
- .maxLines(2)
- .textOverflow({overflow: TextOverflow.Ellipsis})
- .margin({top: 10})
- }
- .padding(4)
- }
- .height(100)
- .backgroundColor(0xF5F5F5)
- .borderRadius(8)
- }
- }
- @Entry
- @Component
- struct Index {
- private eSportsItems: ESports[] = initOnStartup()
- build() {
- Column() {
- Flex({justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center}) {
- Text('電競(jìng)快覽')
- .fontSize(20)
- .fontWeight(FontWeight.Bold)
- .margin(20)
- }
- List({space: 4, initialIndex: 0}) {
- ForEach(this.eSportsItems, item => {
- ListItem() {
- ESportsListItem({eSportsItem: item})
- }
- .onClick(() => {
- router.push({
- uri: 'pages/content',
- params: {eSports: item}
- })
- })
- }, item => item.id.toString())
- }
- .width('96%')
- }
- .width("100%")
- .height("100%")
- .backgroundColor(0xE5E5E5)
- .padding({top: 5})
- }
- }
4. 構(gòu)建電競(jìng)新聞內(nèi)容

- import router from '@system.router';
- import {ESports} from '../model/ESports.ets';
- @Component
- struct PageTitle {
- private eSports: ESports;
- build() {
- Flex({alignItems: ItemAlign.Start}) {
- Image($r('app.media.back'))
- .width(20)
- .height('100%')
- Text(this.eSports.title)
- .height('100%')
- .fontSize(16)
- .fontWeight(FontWeight.Bold)
- .maxLines(1)
- .textOverflow({overflow: TextOverflow.Ellipsis})
- .margin({left: 16})
- }
- .height(61)
- .backgroundColor('#FFedf2f5')
- .padding({top: 13, bottom: 14, left: 12})
- .onClick(() => {
- router.back();
- })
- }
- }
- @Entry
- @Component
- struct Content {
- private eSports: ESports = router.getParams().eSports;
- build() {
- Column() {
- Stack({alignContent: Alignment.TopStart}) {
- PageTitle({eSports: this.eSports})
- }
- Column() {
- Text(this.eSports.title)
- .width('80%')
- .fontSize(14)
- .fontWeight(FontWeight.Bold)
- .maxLines(2)
- .textOverflow({overflow: TextOverflow.Ellipsis})
- .textAlign(TextAlign.Center)
- .padding({top: 8, bottom: 8})
- Row({space: 12}) {
- Text(this.eSports.source)
- .fontSize(12)
- .fontColor('#CCCCCC')
- Text(this.eSports.ctime)
- .fontSize(12)
- .fontColor('#CCCCCC')
- }
- .margin({top: 5, bottom: 10})
- Text(this.eSports.description)
- .width('90%')
- .height(80)
- .lineHeight(20)
- .fontSize(12)
- .maxLines(5)
- .textOverflow({overflow: TextOverflow.Ellipsis})
- .borderRadius(10)
- .backgroundColor(0xE5E5E5)
- .padding(10)
- }
- }
- .alignItems(HorizontalAlign.Center)
- .height('100%')
- .width('100%')
- }
- }
這里預(yù)留一個(gè)思考題:
新聞內(nèi)容是使用文本編輯器或者直接使用的是URL鏈接地址,如何讓它能夠在頁(yè)面中直接顯示?
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)