小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Harmoney北向開發(fā)入門篇(一)鴻蒙開發(fā)套件由七個(gè)主要組件組成。 1. HarmonyOS Design:視覺設(shè)計(jì)。

 oskycar 2024-08-14 發(fā)布于北京

初識(shí)鴻蒙開發(fā)

了解鴻蒙開發(fā)套件

鴻蒙開發(fā)套件由七個(gè)主要組件組成。

  1. HarmonyOS Design:視覺設(shè)計(jì)。
  2. ArkTs:項(xiàng)目開發(fā)語(yǔ)言。
  3. ArkUI:一套UI框架。
  4. ArkCompiler:AOT優(yōu)化,優(yōu)化字節(jié)碼編譯,提高運(yùn)行效率。
  5. DevEco Studio:開發(fā)編譯器;IDEA。
  6. DevEco Testing:面向測(cè)試人員的開發(fā)工具。
  7. AppGallery Connect:分發(fā)運(yùn)營(yíng)套件,提供了很多的云函數(shù)、云數(shù)據(jù)庫(kù)功能。

整個(gè)鴻蒙應(yīng)用的開發(fā)步驟分為三步:

  1. 準(zhǔn)備和設(shè)計(jì)。
  2. 代碼開發(fā)。
  3. 測(cè)試和上架。

而我們作為開發(fā)人員,主要接觸的是DevEco Studio編譯器、ArkTs開發(fā)語(yǔ)言、ArkUI框架。

DevEco Studio安裝

DevEco 的初始化安裝,主要需要三個(gè)東西:nodejs、OHPM包管理器、HarmonyOS SDK。

鴻蒙的編譯器DevEco Studio,需要使用管理員身份執(zhí)行,不然安裝sdk可能會(huì)失敗。

確保最終是全綠,才可以進(jìn)行下一步的項(xiàng)目創(chuàng)建

踩坑

公司電腦加密系統(tǒng)也會(huì)導(dǎo)致DevEco Studio開發(fā)環(huán)境配置不成功。比如 ohpm卡安裝

解決ohpm卡安裝問題

OpenHarmony Ohpm安裝歷程(個(gè)人踩坑,最后安裝成功)-CSDN博客

配置OHPM代理

設(shè)置Ohpm代理

找到FIle->Settings->Ohpm,點(diǎn)擊Optimize config。

彈出以下彈窗:

ohpm registry:配置ohpm倉(cāng)的地址信息,repo./ohpm/

如果需要設(shè)置網(wǎng)絡(luò)代理,那么可以勾選HTTP proxy并進(jìn)行配置。

關(guān)閉Windows defender

關(guān)閉defender,或者將devEco相關(guān)內(nèi)容添加到排除項(xiàng)

運(yùn)行首個(gè)項(xiàng)目

  1. 創(chuàng)建項(xiàng)目

創(chuàng)建首個(gè)項(xiàng)目,選擇Create Project->Empty Ability,由此可知Ability等于安卓的Activity。

  1. 模擬器的配置

(和Android studio其實(shí)差不大多,摸索就行),DevEco Studio支持Remote 云控模擬器,還是很有意思的。

  1. 運(yùn)行項(xiàng)目

點(diǎn)擊run運(yùn)行,helloworld就有了

了解ArkTS

以前學(xué)習(xí)的HTML網(wǎng)頁(yè)開發(fā),它包含了H5+CSS+JavaScript,從而實(shí)現(xiàn)了一個(gè)完整的網(wǎng)頁(yè)結(jié)構(gòu)。

那么也就意味著如果要掌握網(wǎng)頁(yè)開發(fā),需要同時(shí)掌握HTML語(yǔ)法、CSS語(yǔ)法、JavaScript語(yǔ)法,需要掌握三樣內(nèi)容。

而ArkTS相比起H5來說則更加容易,只需要掌握ArkTS這一門語(yǔ)言就可以完成UI和交互邏輯的開發(fā)工作了。

ArkTS與Typescript

  • ArkTS基于Typescript,而Typescript基于JavaScript;Typescript相比較于JavaScript新增了靜態(tài)類型定義功能;所以ArkTS也具有Typescript的這些特性。
  • ArkTS可以理解為等同于網(wǎng)頁(yè)的JavaScript。同時(shí),ArkTS又拓展了聲明式UI、狀態(tài)管理等特性。

ArkTS的優(yōu)點(diǎn)

  • 開發(fā)效率高、開發(fā)體驗(yàn)好。
  • 性能優(yōu)越。
  • 有多系統(tǒng)適配,接入能力。

ArkTS雖然使用的是聲明式UI,但是它底層有個(gè)方舟編譯器,方舟編譯器會(huì)幫我們把寫的TS語(yǔ)言編譯成字節(jié)碼,最終轉(zhuǎn)為機(jī)器碼。而且還會(huì)把 字節(jié)碼轉(zhuǎn)換為機(jī)器碼的 動(dòng)作,從運(yùn)行器提前到編譯期,從而大大提高運(yùn)行效率。
以及還有一套UI后端引擎,提供了一套統(tǒng)一的頁(yè)面渲染的指令,這些指令最后提供給渲染總線,最終渲染總線將指令傳遞給了高效渲染引擎;高效渲染引擎會(huì)對(duì)我們的UI指令再進(jìn)行一層的優(yōu)化,大大提高頁(yè)面渲染效率。

同時(shí)鴻蒙系統(tǒng)底層對(duì)ArkTS提供了不同平臺(tái)的適配層和橋接層。

因此,ArkTS開發(fā)的鴻蒙應(yīng)用,不僅簡(jiǎn)單,性能也很好,而且具有跨系統(tǒng)適配能力。

Typescript基礎(chǔ)語(yǔ)法

Typescript演練場(chǎng)

訪問Typescript官網(wǎng),點(diǎn)擊Playground,可以進(jìn)入到Typescript演練場(chǎng)、,在此處可以練習(xí)Typescript語(yǔ)法。

變量聲明

  • Typescript在JavaScript的基礎(chǔ)上加入了靜態(tài)類型檢查功能,因此每一個(gè)變量都有固定的數(shù)據(jù)類型。
csharp
代碼解讀
復(fù)制代碼
let msg:string='hello world'//聲明一個(gè)string類型的msg變量。

let:聲明變量的關(guān)鍵幀。也可以使用const,表示常量。

msg:變量名。

string:變量的數(shù)據(jù)類型;Typescript相較于JavaScript就是多了這一部分變量的數(shù)據(jù)類型聲明。

'hello world':賦的值;可以使用單引號(hào)',也可以使用雙引號(hào)""。

數(shù)據(jù)類型

  • string:字符串
csharp
代碼解讀
復(fù)制代碼
let msg:string='hello world'
    • 字符串拼接時(shí),通過使用 符號(hào),可以開啟 ${} (單/雙引號(hào)下不支持)。
ini
代碼解讀
復(fù)制代碼
const anExampleVariable = "Hello World" console.log(`輸出anExampleVariable=${anExampleVariable}`) //打印結(jié)果:輸出anExampleVariable=Hello World
  • number:數(shù)值類型;不區(qū)分整數(shù)、浮點(diǎn)數(shù),都使用number。
ini
代碼解讀
復(fù)制代碼
let age:number=18
  • boolean:布爾類型
ini
代碼解讀
復(fù)制代碼
let finished:boolean=true
  • any:不確定類型,可以是任意的類型。
ini
代碼解讀
復(fù)制代碼
let a:any='jack' a=21;
  • union:聯(lián)合類型,可以是多個(gè)指定類型的一種。
ini
代碼解讀
復(fù)制代碼
//聯(lián)合類型U,可以是string,也可以number、boolean;它們的數(shù)據(jù)類型可以自由切換。 let u:string|number|boolean="union"; u=100;
  • object:對(duì)象
css
代碼解讀
復(fù)制代碼
// 聲明了一個(gè)對(duì)象,類別兩個(gè)變量name,age。它們的值對(duì)應(yīng) name為jack,age為24. let p={name:'jack',age:24} //在控制臺(tái)輸出對(duì)象p的name屬性。 console.log(p.name); console.log(p['name']);
  • Array:數(shù)組;內(nèi)部的元素可以是任意類型。
typescript
代碼解讀
復(fù)制代碼
let names:Array<string>=['Jack','Rose'] let ages:number[]=[20,21] console.log(names[0]) console.log(ages[0].toString())

注意:

  • 開發(fā)時(shí)通常是在函數(shù)中會(huì)用到any、union類型。
  • 聲明普通變量時(shí),盡可能不使用any。

條件控制

Typescript和大多數(shù)語(yǔ)言類似,都是支持if-else、switch 條件控制語(yǔ)句的。

typescript
代碼解讀
復(fù)制代碼
let num:number=88; //判斷奇偶數(shù) if(num%2===0){ console.log("是偶數(shù)!") }else{ console.log("是奇數(shù)!") } //判斷是否正數(shù) if(num>0){ console.log("是正數(shù)!") }else if(num<0){ console.log("是負(fù)數(shù)!") }else{ console.log("是0!") } [LOG]: "是偶數(shù)!" [LOG]: "是正數(shù)!"
c
代碼解讀
復(fù)制代碼
let grade:string="A"; switch(grade){ case "A" : console.log("優(yōu)秀") break case "B": console.log("及格") break case "C": console.log("不及格") break default: console.log("非法輸入") break } [LOG]: "優(yōu)秀"

注意:

  • 在Typescript中,空字符串、數(shù)字0、null、undefind都被認(rèn)為是false,其他值則為true。

比較運(yùn)算符:== 與 ===

  • 在Typescript中,比較運(yùn)算符 '=='(相等運(yùn)算符) 和 '==='(嚴(yán)格相等運(yùn)算符) 都可以用于比較兩個(gè)值是否相等,但是==如果比較的兩個(gè)值類型不同,那么它會(huì)主動(dòng)的對(duì)數(shù)據(jù)類型進(jìn)行強(qiáng)制轉(zhuǎn)換為相同的類型后再比較,這樣的話比較損耗性能。
    所以建議優(yōu)先使用 === 嚴(yán)格相等運(yùn)算符。

循環(huán)迭代

Typescript支持for和while循環(huán),并且為一些內(nèi)置類型如Array等提供了快捷迭代語(yǔ)法。

  • for:常規(guī)for循環(huán)。
  • while:常規(guī)while循環(huán)。
  • for in 遍歷:得到數(shù)組索引角標(biāo)。
  • for of遍歷:得到數(shù)組元素。
typescript
代碼解讀
復(fù)制代碼
//for循環(huán) for(let i=0;i<10;i++){ //輸出0-9 console.log("for循環(huán),i="+i) } //while循環(huán) let i=0; while(i<10){ //輸出0-9 console.log("while循環(huán),i="+i) i++; } let list:Array<string>=['A','B','C','D','E'] //for in 迭代器,遍歷得到數(shù)組角標(biāo)索引。 for(const i in list){ //輸出數(shù)組角標(biāo) console.log("for in 迭代獲取list角標(biāo),i="+i) //輸出數(shù)組的元素內(nèi)容 console.log("for in 迭代打印數(shù)組內(nèi)容,第"+i+"個(gè)為"+list[i]) } //for of 迭代器,遍歷得到數(shù)組元素 for(const item of list){ //輸出數(shù)組內(nèi)的元素內(nèi)容 console.log("for of 迭代打印list數(shù)組內(nèi)容, item="+item) }

函數(shù)

Typescript通常利用function關(guān)鍵字聲明函數(shù),并且支持可選參數(shù)、默認(rèn)參數(shù)、箭頭函數(shù)等特殊語(yǔ)法。

  • 無返回值函數(shù)
  • 有返回值函數(shù)
  • 箭頭函數(shù)
    語(yǔ)法:let 函數(shù)名 =(參數(shù)名:參數(shù)類型)=>{ ... } 代碼塊內(nèi)部可以 return 返回任意類型的數(shù)據(jù)。
typescript
代碼解讀
復(fù)制代碼
//無返回值函數(shù),返回值void可以省略。 function sayHello(name:string):void{//:void 表示無返回值,可省略。 console.log("你好,"+name) } sayHello("張三") //有返回值的函數(shù) function sum(x:number,y:number):number{ return x+y; } console.log("1+1="+sum(1,1)); //箭頭函數(shù) let sayHi=(name:string)=>{ console.log("你好,"+name) } sayHi("李四")

可選參數(shù)

可選參數(shù),表示函數(shù)在被調(diào)用時(shí),可選參數(shù)是可以不傳值的。

scss
代碼解讀
復(fù)制代碼
//可選參數(shù),在參數(shù)名后面添加?符號(hào),表示該參數(shù)是可選的 function sayHello(name?:string){ console.log(name)//輸出:undefined //檢查是否為name參數(shù)傳入值 name=name?name:"陌生人" console.log("你好,"+name)//輸出:"你好,陌生人" } sayHello()

默認(rèn)參數(shù)

默認(rèn)參數(shù),表示參數(shù)具有默認(rèn)值,如果調(diào)用時(shí)該參數(shù)未傳值,則使用默認(rèn)值。

c
代碼解讀
復(fù)制代碼
//默認(rèn)參數(shù),在參數(shù)類型后面添加 ="默認(rèn)值" function sayHello(name:string="陌生人"){ console.log(name)//輸出:陌生人 //檢查是否為name參數(shù)傳入值 name=name?name:"陌生人" console.log("你好,"+name)//輸出:你好,陌生人 } sayHello()

類和接口

Typescript具備面向?qū)ο缶幊痰幕菊Z(yǔ)法,例如interface、class、enum等。也具備封裝、繼承、多態(tài)等面向?qū)ο蠡咎卣鳌?/p>

php
代碼解讀
復(fù)制代碼
//定義枚舉 enum Msg{ HI="Hi", HELLO="Hello", } //定義接口 interface A{ say(msg:Msg):void } //實(shí)現(xiàn)接口 class B implements A{ say(msg:Msg):void{ console.log(msg+",I'm B") } } //創(chuàng)建B的實(shí)例對(duì)象 let b:B=new B(); b.say(Msg.HELLO) //輸出:"Hello,I'm B"

總結(jié):

  • 枚舉:
    • 枚舉支持賦值(支持任意類型,不需要聲明),如果不賦值,則默認(rèn)從0開始,按照順序每個(gè)枚舉值默認(rèn)+1。
    • 如果枚舉中有一個(gè)成員定義了值,那么其他枚舉元素也必須要定義值,無法再使用默認(rèn)的值。
    • 枚舉中每個(gè)成員的數(shù)據(jù)類型可以存在不同。
  • 在接口中定義的函數(shù)、類中實(shí)現(xiàn)的接口函數(shù)中,函數(shù)不需要添加function關(guān)鍵字。
  • Typescript中對(duì)象的創(chuàng)建是通過new關(guān)鍵字來實(shí)現(xiàn)的。

typescript
代碼解讀
復(fù)制代碼
//定義矩形類 class Rectangle{ //成員變量 //定義類中成員變量時(shí),不需要添加let關(guān)鍵字。 //private關(guān)鍵字表示當(dāng)前成員變量為私有的。成員變量默認(rèn)的訪問權(quán)限是public。 private mWidth:number private mLength:number //構(gòu)造函數(shù) constructor(width:number,length:number){ //在函數(shù)中操作成員變量時(shí),必須用 this 去獲取變量。不使用this的話就無法操作成員變量。 this.mWidth=width this.mLength=length } //成員函數(shù) public area():number{ return this.mWidth+this.mLength } } //定義正方形類 class Square extends Rectangle{ //定義構(gòu)造函數(shù) constructor(side:number){ //調(diào)用父類的構(gòu)造函數(shù) super(side,side) } } let sq=new Square(5) console.log("正方形的面積為:"+sq.area()) //輸出:"正方形的面積為:10"

總結(jié):

  • 定義類中的成員變量時(shí),不需要添加let關(guān)鍵字。
  • 在類函數(shù)中操作當(dāng)前類的成員變量時(shí),必須用 this 去獲取變量。不使用this的話就無法操作成員變量。、
  • 類的構(gòu)造函數(shù)不需要函數(shù)名。
  • 在 TypeScript 中,類的成員(包括屬性和方法)的訪問權(quán)限默認(rèn)是 public。
    TypeScript中的訪問修飾符:public、private、protected
  • extends:繼承。
get、set函數(shù)

private 修飾的成員變量是受保護(hù)的,在類的外面無法進(jìn)行直接賦值和取值;但是是可以使用 get、set 方法來對(duì) private 修飾的成員變量進(jìn)行賦值和取值

在Typescript中也有g(shù)et、set函數(shù);它們的使用方式為:

  • get 函數(shù)名():變量類型
  • set 函數(shù)名(入?yún)ⅲ鹤兞款愋?

注意:

  • 使用 get、set方法的成員變量命名時(shí)建議在前面加 _
  • get 和 set 方法的名稱,建議使用去掉 _ 的成員變量名稱
  • 在類外使用時(shí),通過操作get和set修飾的方法名(以對(duì)象屬性的方式操作),來間接的操作成員變量
csharp
代碼解讀
復(fù)制代碼
export class NameBean{ private _name:string;//名稱 get name():string{ return this._name } set name(setName:string){ this.name=setName } }

模塊開發(fā)

當(dāng)應(yīng)用復(fù)雜時(shí),我們可以把通用功能抽取到單獨(dú)的TS文件中,每個(gè)TS文件都是一個(gè)模塊(moudle)。模塊可以相互加載,提高代碼復(fù)用性。

在Typescript中,我們可以將想要提供給其他TS文件使用的函數(shù)、變量、類進(jìn)行導(dǎo)出(export),如下代碼:
使用export修飾class、 function,從而導(dǎo)出給其他TS文件使用。

typescript
代碼解讀
復(fù)制代碼
//定義矩形類,并使用export導(dǎo)出。 export class Rectangle{ //成員變量 public mWidth:number public mLength:number //構(gòu)造函數(shù) constructor(width:number,length:number){ this.mWidth=width this.mLength=length } } export function area(rec:Rectangle):number{ return rec.mWidth+rec.mLength }

在其他模塊(TS文件)中,將可導(dǎo)出的功能導(dǎo)入(import)到當(dāng)前模塊內(nèi)使用:

javascript
代碼解讀
復(fù)制代碼
//通過import語(yǔ)法導(dǎo)入其他TS文件的功能,from后面寫文件的地址 //import語(yǔ)句建議放在代碼頂部。 import {Rectangle,area} from '../rectangle' //導(dǎo)入功能后,可以在當(dāng)前文件內(nèi)任意地方進(jìn)行Rectangle、area的調(diào)用。 //創(chuàng)建Rectangle對(duì)象 let r = new Rectangle(10,20) //調(diào)用area方法 console.log("面積為:"+area(r))

了解Harmony基本工程目錄

Ohos項(xiàng)目結(jié)構(gòu)分類

將項(xiàng)目的目錄視圖,切換到鴻蒙的Ohos視圖

  • AppScope中存放應(yīng)用全局所需要的資源文件。
  • Entry是entry是應(yīng)用的主模塊,存放HarmonyOS應(yīng)用的代碼、資源等。
    • ets文件夾內(nèi)存放代碼編寫文件(我們開發(fā)主要集中在ets文件夾中)
      • page存放頁(yè)面 :index.ets是初始頁(yè)面
    • configuration則存放相應(yīng)模塊配置文件
    • resources對(duì)應(yīng)文件公共資源
  • 最外層的configuration,存放工程應(yīng)用級(jí)的配置文件
    • build-profile.json5是工程級(jí)配置信息,包括簽名、產(chǎn)品配置等。
    • hvigorfile.ts是工程級(jí)編譯構(gòu)建任務(wù)腳本,hvigor是基于任務(wù)管理機(jī)制實(shí)現(xiàn)的一款全新的自動(dòng)化構(gòu)建工具,主要提供任務(wù)注冊(cè)編排,工程模型管理、配置管理等核心能力。
    • oh-package.json5是工程級(jí)依賴配置文件,用于記錄引入包的配置信息。
  • 在AppScope,其中有resources文件夾和配置文件app.json5。AppScope > resources> base文件夾中包含element和media兩個(gè)文件夾
    • 其中element文件夾主要存放公共的字符串、布局文件等資源。
    • media存放全局公共的多媒體資源文件。
  • 將項(xiàng)目切換到 project 視圖:oh_modules 是工程的依賴包,存放工程依賴的源文件。

module結(jié)構(gòu)分類

接下來看模塊中的結(jié)構(gòu)分類:

  • entry模塊下的src目錄中主要包含總的main文件夾,單元測(cè)試目錄ohosTest,以及模塊級(jí)的配置文件。
  • main文件夾中,ets文件夾用于存放ets代碼,resources文件存放模塊內(nèi)的多媒體及布局文件等,module.json5文件為模塊的配置文件。
  • ohosTest是單元測(cè)試目錄。
  • build-profile.json5是模塊級(jí)配置信息,包括編譯構(gòu)建配置項(xiàng)
  • hvigorfile.ts文件是模塊級(jí)構(gòu)建腳本。
  • oh-package.json5是模塊級(jí)依賴配置信息文件。
  • 進(jìn)入src>main>ets目錄中,其分為entryability、pages兩個(gè)文件夾。
    • entryability存放ability文件,用于當(dāng)前ability應(yīng)用邏輯和生命周期管理。
    • pages存放UI界面相關(guān)代碼文件,初始會(huì)生成一個(gè)Index頁(yè)面。
  • resources目錄下存放模塊公共的多媒體、字符串及布局文件等資源,分別存放在element、media文件夾中。

app.json5

AppScope下的app.json5是應(yīng)用的全局的配置文件,用于存放應(yīng)用公共的配置信息。

其中配置信息如下:

  • bundleName是包名。
  • vendor是應(yīng)用程序供應(yīng)商。
  • versionCode是用于區(qū)分應(yīng)用版本。
  • versionName是版本號(hào)。
  • icon對(duì)應(yīng)于應(yīng)用的顯示圖標(biāo)。
  • label是應(yīng)用名。

module.json5

模塊的配置文件,包含當(dāng)前模塊的配置信息。mainElement指定啟動(dòng)首頁(yè)Ability的名稱,abilities中可以聲明多個(gè)Ability。

deviceTypes:聲明了當(dāng)前模塊支持的設(shè)備類型,這里是手機(jī)phone和平板tablet。

entry>src>main>module.json5是模塊的配置文件,包含當(dāng)前模塊的配置信息。

我們簡(jiǎn)單了解以下幾個(gè):

  • name:該標(biāo)簽標(biāo)識(shí)當(dāng)前module的名字,module打包成hap后,表示hap的名稱,標(biāo)簽值采用字符串表示(最大長(zhǎng)度31個(gè)字節(jié)),該名稱在整個(gè)應(yīng)用要唯一;如 entry。
  • mainElement:指定啟動(dòng)首頁(yè)Ability的名稱;該標(biāo)簽標(biāo)識(shí)模塊的入口ability名稱或者extension名稱;如 EntryAbility。
  • deviceTypes:該標(biāo)簽標(biāo)識(shí)hap可以運(yùn)行在哪類設(shè)備上,標(biāo)簽值采用字符串?dāng)?shù)組的表示。如 ["phone",tablet"] 表示當(dāng)前模塊可以運(yùn)行在手機(jī)和平板上。
  • pages:對(duì)應(yīng)的是main_pages.json文件,用于配置ability中用到的page信息。
  • abilities:是一個(gè)數(shù)組,存放當(dāng)前模塊中所有的ability元能力的配置信息,其中可以有多個(gè)ability。
    • name:該標(biāo)簽標(biāo)識(shí)當(dāng)前ability的邏輯名,該名稱在整個(gè)應(yīng)用要唯一,標(biāo)簽值采用字符串表示(最大長(zhǎng)度127個(gè)字節(jié))。
    • srcEntry:當(dāng)前模塊的入口Ability文件路徑。 如:"./ets/entryability/EntryAbility.ts"
kotlin
代碼解讀
復(fù)制代碼
{ "module": { //name:該標(biāo)簽標(biāo)識(shí)當(dāng)前module的名字,module打包成hap后,表示hap的名稱,標(biāo)簽值采用字符串表示(最大長(zhǎng)度31個(gè)字節(jié)),該名稱在整個(gè)應(yīng)用要唯一。 "name": "entry", //type: 表示模塊的類型,類型有三種,分別是entry、feature和har。 "type": "entry", //description:當(dāng)前模塊的描述信息。 "description": "$string:module_desc", //mainElement: 該標(biāo)簽標(biāo)識(shí)hap的入口ability名稱或者extension名稱。只有配置為mainElement的ability或者extension才允許在服務(wù)中心露出。 "mainElement": "EntryAbility", //deviceTypes:該標(biāo)簽標(biāo)識(shí)hap可以運(yùn)行在哪類設(shè)備上,標(biāo)簽值采用字符串?dāng)?shù)組的表示。 "deviceTypes": [ "phone", "tablet" ]], //deliveryWithInstall:標(biāo)識(shí)當(dāng)前Module是否在用戶主動(dòng)安裝的時(shí)候安裝,表示該Module對(duì)應(yīng)的HAP是否跟隨應(yīng)用一起安裝。 // - true:主動(dòng)安裝時(shí)安裝。- false:主動(dòng)安裝時(shí)不安裝。 "deliveryWithInstall": true, //installationFree:標(biāo)識(shí)當(dāng)前Module是否支持免安裝特性。- true:表示支持免安裝特性,且符合免安裝約束。- false:表示不支持免安裝特性。 "installationFree": false, //pages:對(duì)應(yīng)的是main_pages.json文件,用于配置ability中用到的page信息。 "pages": "$profile:main_pages", //abilities:是一個(gè)數(shù)組,存放當(dāng)前模塊中所有的ability元能力的配置信息,其中可以有多個(gè)ability。 "abilities": [ { //name:該標(biāo)簽標(biāo)識(shí)當(dāng)前ability的邏輯名,該名稱在整個(gè)應(yīng)用要唯一,標(biāo)簽值采用字符串表示(最大長(zhǎng)度127個(gè)字節(jié))。 "name": "EntryAbility", //srcEntry:當(dāng)前模塊的入口文件路徑。 "srcEntry": "./ets/entryability/EntryAbility.ts", //description:ability的描述信息。 "description": "$string:EntryAbility_desc", // icon:ability的圖標(biāo)。該標(biāo)簽標(biāo)識(shí)ability圖標(biāo),標(biāo)簽值為資源文件的索引。該標(biāo)簽可缺省,缺省值為空。 // 如果ability被配置為MainElement,該標(biāo)簽必須配置。 "icon": "$media:icon", //label: ability的標(biāo)簽名。 "label": "$string:EntryAbility_label", //startWindowIcon 啟動(dòng)頁(yè)面的圖標(biāo)。 "startWindowIcon": "$media:icon", //startWindowBackground: 啟動(dòng)頁(yè)面的背景色。 "startWindowBackground": "$color:start_window_background", "exported": true, // skills:標(biāo)識(shí)能夠接收的意圖的action值的集合,取值通常為系統(tǒng)預(yù)定義的action值,也允許自定義。 "skills": [ { "entities": [ "entity.system.home" ], "actions": [ "action.system.home" ] } ] // visible:ability是否可以被其他應(yīng)用程序調(diào)用,true表示可以被其它應(yīng)用調(diào)用, false表示不可以被其它應(yīng)用調(diào)用。 // entities:標(biāo)識(shí)能夠接收Want的Entity值的集合。 // actions:標(biāo)識(shí)能夠接收的Want的Action值的集合,取值通常為系統(tǒng)預(yù)定義的action值,也允許自定義。 } ] } }

main_pages.json

entry/src/main/resources/base/profile/main_pages.json文件保存的是當(dāng)前模塊中頁(yè)面page的路徑配置信息,所有需要進(jìn)行路由跳轉(zhuǎn)的page頁(yè)面都要在這里進(jìn)行配置。

index.ets

less
代碼解讀
復(fù)制代碼
@Entry @Component struct Index { @State message: string = 'Hello World' build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) .fontColor("#36D") // .onClick(()=>{ // //處理事件 // }) .onClick((event)=>{ //處理??件 }) .width('100%') } .height('100%') } }

  • struct index{ }:在上述代碼中聲明了一個(gè)自定義組件index,自定義組件是可復(fù)用的UI單元。
    但是自定義組件不能僅僅靠關(guān)鍵詞struct,還需要添加 裝飾器 標(biāo)記來聲明當(dāng)前結(jié)構(gòu)體的信息。
    被 @Component 裝飾器修飾的結(jié)構(gòu)體,才能稱為自定義結(jié)構(gòu)體組件。
    從java注解漫談到typescript裝飾器——注解與裝飾器
  • 裝飾器:用來裝飾類結(jié)構(gòu)、方法、變量
    • @Entry:用來修飾結(jié)構(gòu)體組件;標(biāo)記當(dāng)前組件是入口組件,也就是當(dāng)前組件是支持被獨(dú)立訪問的。即一個(gè)頁(yè)面。
      如果組件不添加@Entry,那么這個(gè)組件就是普通組件。
      預(yù)覽器只會(huì)預(yù)覽使用了@Enrty裝飾器的組件。
    • @Component:用來修飾結(jié)構(gòu)體組件;標(biāo)記聲明為 自定義組件
    • @State:用來修飾變量;標(biāo)記這個(gè)變量為狀態(tài)變量,值變化時(shí)會(huì)觸發(fā)對(duì)應(yīng)的UI刷新。
  • build(){ } 函數(shù):其內(nèi)部以聲明式方式描述UI結(jié)構(gòu)。
    如上述代碼中的Row()、Column()、Text()都是ArkTS提供的組件。
    這些組件也分為兩類:
    • 容器組件:用來完成頁(yè)面布局,例如:Row、Column。
    • 基礎(chǔ)組件:自帶樣式和功能的頁(yè)面元素,例如 Text文本組件。
  • UI樣式的屬性方法:設(shè)置組件的UI樣式。
    通過調(diào)用自定義組件提供的屬性方法,來修改組件樣式信息,
    如 fontsize()設(shè)置字體大小,fontweight設(shè)置字體粗細(xì),fontColor設(shè)置字體顏色,等等。
  • UI事件方法(監(jiān)聽):設(shè)置組件的事件回調(diào)。
    UI組件支持設(shè)置例如 點(diǎn)擊 等事件的監(jiān)聽。如:onClick(()=>{ //處理事件... }) 在View被點(diǎn)擊時(shí)會(huì)觸發(fā)方法塊里的代碼。

EntryAbility.ts

javascript
代碼解讀
復(fù)制代碼
import UIAbility from '@ohos.app.ability.UIAbility'; import hilog from '@ohos.hilog'; import window from '@ohos.window'; export default class EntryAbility extends UIAbility { onCreate(want, launchParam) { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); } onDestroy() { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); } onWindowStageCreate(windowStage: window.WindowStage) { // Main window is created, set main page for this ability hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); windowStage.loadContent('pages/Index1', (err, data) => { if (err.code) { hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); return; } hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); }); } onWindowStageDestroy() { // Main window is destroyed, release UI related resources hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); } onForeground() { // Ability has brought to foreground hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); } onBackground() { // Ability has back to background hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); } }

類似Activity,這里面有很多內(nèi)置的生命周期,如創(chuàng)建、銷毀;前臺(tái)、后臺(tái)。

ArkUI-組件

ArkUI提供的常用組件

Image:圖片顯示組件

Image通常用來加載圖片顯示。

  1. 聲明Image組件并設(shè)置圖片源
php
代碼解讀
復(fù)制代碼
Image(src:string|PixelMap|Resource)

入?yún)?shù)據(jù)類型介紹:

    • string格式:通常用來加載網(wǎng)絡(luò)圖片,應(yīng)用訪問網(wǎng)絡(luò)需要聲明網(wǎng)絡(luò)訪問權(quán)限:ohos.permission.INTERNET。
      Image("....png")
    • PixelMap格式:可以加載像素圖,常用在圖片編輯中。該方式使用較復(fù)雜。
      Image(pixelMapObject)
    • Resource格式:加載資源圖片,推薦使用此種方式。
      • 方式1:Image( **r??(app.media.icon))r 方式的路徑則是對(duì)應(yīng)了src的resource文件夾中media目錄中的icon圖標(biāo)。
        該方式可以省略文件的后綴名。
      • 方式2:Image( **rawfile??(gmzr.png))rawfile 方式則是對(duì)應(yīng)了src的resource文件夾中rawfile目錄下的 gmzr.png 文件
        當(dāng)前方式不允許省略文件后綴名。
  1. 添加圖片屬性
scss
代碼解讀
復(fù)制代碼
Image($r("app.media.icon")) .objectFit(ImageFit.Cover)//設(shè)置圖片縮放效果,默認(rèn)Cover .width(50)//寬度 .height(50)//高度 .borderRadius(10)//邊框圓角,不設(shè)置時(shí)默認(rèn)方角。 .interpolation(ImageInterpolation.High)//圖片插值:將不清晰圖片的鋸齒消除,提高圖片清晰度。

圖片適應(yīng)模式

objectFit方法屬性用于設(shè)置圖片的適應(yīng)模式,參數(shù)類型是ImageFit;
ImageFit包含以下幾種類型:

  • Contain:保持寬高比進(jìn)行縮小或者放大,使得圖片完全顯示在顯示邊界內(nèi)。
  • Cover(默認(rèn)值):保持寬高比進(jìn)行縮小或者放大,使得圖片兩邊都大于或等于顯示邊界。
  • Auto:自適應(yīng)顯示。
  • Fill:不保持寬高比進(jìn)行放大縮小,使得圖片充滿顯示邊界。
  • ScaleDown:保持寬高比顯示,圖片縮小或者保持不變。
  • None:保持原有尺寸顯示。

網(wǎng)絡(luò)權(quán)限申請(qǐng)

加載網(wǎng)絡(luò)圖片時(shí),需要配置文件權(quán)限聲明應(yīng)用權(quán)限列表

kotlin
代碼解讀
復(fù)制代碼
{ "module" : { // ... "requestPermissions":[ { //申請(qǐng)網(wǎng)絡(luò)權(quán)限 "name": "ohos.permission.INTERNET", }, { //示例: "name" : "ohos.permission.PERMISSION1", "reason": "$string:reason", "usedScene": { "abilities": [ "FormAbility" ], "when":"inuse" } } ] } }

UI組件寬高設(shè)置

UI組件的寬高設(shè)置有三種方式:

  • 直接在width函數(shù)中寫數(shù)值,如 .width(50),這樣的話會(huì)默認(rèn)使用vp虛擬像素作為寬度的單位,即 50vp。
    vp是鴻蒙的一種虛擬像素,用來適配多分辨率設(shè)備而存在,理解為安卓的dp。
    推薦使用此方式。
  • 使用字符串類型的數(shù)值,如 .width("50"),該方式的單位則是像素px,多分辨率下適配性會(huì)不太好。
  • 使用字符串類型的百分比,如 .width("100%"),該方式的單位是百分比,表示占當(dāng)前組件父布局的百分比。

官方文檔查看快捷方式

將鼠標(biāo)懸停在組件上,點(diǎn)擊Show in API Reference,即可打開官方組件文檔。

Text:文本顯示組件

  1. 聲明Text組件并設(shè)置文本內(nèi)容:
scss
代碼解讀
復(fù)制代碼
Text(content?:string|Resource)

文本內(nèi)容來源有兩個(gè)方式:

  • string格式:自己傳入的字符串,會(huì)直接顯示在Text組件中。
scss
代碼解讀
復(fù)制代碼
Text("文本內(nèi)容")
  • Resource格式:來自資源文件的字符串,如
bash
代碼解讀
復(fù)制代碼
Text($r("app.string.EntryAbility_label"))

當(dāng)前系統(tǒng)語(yǔ)言為中文時(shí),這種方式則是從 Resource\zh_CN\string.json 文件中獲取對(duì)應(yīng)name為EntryAbility_label的值來顯示。

  1. 設(shè)置Text的成員屬性
scss
代碼解讀
復(fù)制代碼
Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) .fontColor("#36D")
    • fontSize:設(shè)置字體大小。
    • fontweight:設(shè)置字體的粗細(xì)。
    • fontColor:設(shè)置文字顏色。
    • 更多的API參考官方API文檔。
名稱參數(shù)類型描述
fontColorResourceColor設(shè)置文本顏色。
fontSizeLengthResource設(shè)置文本尺寸,Length為number類型時(shí),使用fp單位。
fontStyleFontStyle設(shè)置文本的字體樣式。默認(rèn)值:FontStyle.Normal。
fontWeightnumberFontWeightstring設(shè)置文本的字體粗細(xì),number類型取值[100, 900],取值間隔為100,默認(rèn)為400,取值越大,字體越粗。string類型僅支持number類型取值的字符串形式,例如“400”,以及“bold”、“bolder”、“l(fā)ighter”、“regular”、“medium”,分別對(duì)應(yīng)FontWeight中相應(yīng)的枚舉值。默認(rèn)值:FontWeight.Normal。
fontFamilystringResource設(shè)置文本的字體列表。使用多個(gè)字體,使用“,”進(jìn)行分割,優(yōu)先級(jí)按順序生效。例如:“Arial,sans-serif”。
textAlignTextAlign設(shè)置文本的對(duì)齊方式。Start(默認(rèn)值):水平對(duì)齊首部。Center:水平居中對(duì)齊。 End:水平對(duì)齊尾部。
decorationTextDecorationType設(shè)置文本裝飾線樣式及其顏色。{ type: TextDecorationType.Underline, color: Color.Black } 給文本設(shè)置了下劃線,下劃線顏色為黑色

多語(yǔ)言適配

鴻蒙APP的多語(yǔ)言適配和Android差不多,在Resource文件夾下生成多個(gè)目錄,每個(gè)目錄按照指定的規(guī)則命名。之后APP會(huì)根據(jù)所運(yùn)行在的系統(tǒng)語(yǔ)言版本 從對(duì)應(yīng)的目錄下讀取string.json,并展示對(duì)應(yīng)文本。

base目錄:默認(rèn)目錄,當(dāng)找不到相對(duì)應(yīng)的語(yǔ)言版本時(shí),默認(rèn)從base查找。

en_US目錄:英文的資源目錄,當(dāng)系統(tǒng)語(yǔ)言為英語(yǔ)時(shí),優(yōu)先從當(dāng)前目錄下讀取文本。

zh_CN目錄:中文的資源目錄,當(dāng)系統(tǒng)語(yǔ)言為中文時(shí),優(yōu)先從當(dāng)前目錄下讀取文本。

TextInput:文本輸入框

TextInput組件用于輸入單行文本,響應(yīng)輸入事件。

  1. 聲明TextInput組件:
scss
代碼解讀
復(fù)制代碼
TextInput({placeholder?:ResourceStr,text?:ResourceStr})
    • placeholder:輸入框無文本時(shí)的提示文本
    • text:輸入框當(dāng)前的文本內(nèi)容
less
代碼解讀
復(fù)制代碼
@State mImgWidth: number = 300 TextInput({ placeholder: "請(qǐng)輸入指定寬度", text: "" + this.mImgWidth }) .type(InputType.Number) .onChange((value) => { if (value != this.mImgWidth.toString() && value.length > 0) { this.mImgWidth = Number.parseInt(value) } })
  1. 添加屬性和事件
scss
代碼解讀
復(fù)制代碼
TextInput({text:"當(dāng)前輸入文本"}) .width(150)//寬 .height(30)//高 .backgroundColor("#FFF")//輸入框背景色 .type(InputType.Password)//輸入框類型,如密碼類型 .onChange((value) => {//設(shè)置文字變化監(jiān)聽 if (value != this.mImgWidth.toString() && value.length > 0) { this.mImgWidth = Number.parseInt(value) } })
    • width:寬度。
    • height:高度。
    • backgroundColor:輸入框背景色。
    • type:設(shè)置輸入類型。
名稱描述
Normal基本輸入模式。支持輸入數(shù)字、字母、下劃線、空格、特殊字符。
Number純數(shù)字輸入模式。
PhoneNumber電話號(hào)碼輸入模式。支持輸入數(shù)字、+、-、*,長(zhǎng)度不限制。
Email郵箱地址輸入模式。支持?jǐn)?shù)字、字母、下劃線、@字符。
Password密碼輸入模式。支持輸入數(shù)字、字母、下劃線、空格、特殊字符。
    • onChange((value) => {}):設(shè)置文字輸入變化事件監(jiān)聽

設(shè)置光標(biāo)位置

使用TextInputController動(dòng)態(tài)設(shè)置。

less
代碼解讀
復(fù)制代碼
@Entry @Component struct TextInputDemo { controller: TextInputController = new TextInputController()//創(chuàng)建控制器 build() { Column() { TextInput({ controller: this.controller })//在這里設(shè)置控制器 Button('設(shè)置光標(biāo)位置') .onClick(() => { this.controller.caretPosition(2)//事件觸發(fā)式,通過caretPosition函數(shù)來修改光標(biāo)位置。 }) } .height('100%') .backgroundColor(0xE6F2FD) } }

獲取輸入文本

我們可以給TextInput設(shè)置onChange事件,輸入文本發(fā)生變化時(shí)觸發(fā)回調(diào)

scss
代碼解讀
復(fù)制代碼
@Entry @Component struct TextInputDemo { @State text: string = '' build() { Column() { TextInput({ placeholder: '請(qǐng)輸入賬號(hào)' }) .caretColor(Color.Blue) .onChange((value: string) => { //在此處監(jiān)聽文字變化后的完整文本。 this.text = value }) Text(this.text) } .alignItems(HorizontalAlign.Center) .padding(12) .backgroundColor(0xE6F2FD) } }

Button:按鈕組件

Button組件主要用來響應(yīng)點(diǎn)擊操作,可以包含子組件。

  1. 聲明Button組件,label是按鈕文字
css
代碼解讀
復(fù)制代碼
Button(label?:ResourceStr)
    • ResourceStr:可以傳普通字符串,也可以傳string文件中的文本。
    • 按鈕有兩種類型,傳遞了文字則是文字型按鈕,不傳遞文字則是自定義按鈕。
      • 文字型按鈕:
less
代碼解讀
復(fù)制代碼
Button("按鈕")
      • 自定義按鈕,在Button內(nèi)嵌套其他組件:
scss
代碼解讀
復(fù)制代碼
Button(){ ImageView($r("app.media.search")).width(20).height(10) }
  1. 添加屬性和事件
scss
代碼解讀
復(fù)制代碼
Button("點(diǎn)我") .width(100) .height(30) .type(ButtonType.Normal) .onclick(()=>{ //處理點(diǎn)擊事件 })
  • type:按鈕類型。
    • Capsule:膠囊型按鈕(圓角默認(rèn)為高度的一半)
    • Circle:圓形按鈕
    • Normal:普通按鈕(默認(rèn)不帶圓角)

LoadingProgress:加載中組件

LoadingProgress組件用于顯示加載進(jìn)展,比如應(yīng)用的登錄界面,當(dāng)我們點(diǎn)擊登錄的時(shí)候,顯示的“正在登錄”的進(jìn)度條狀態(tài)。LoadingProgress的使用非常簡(jiǎn)單,只需要設(shè)置顏色和寬高就可以了。

scss
代碼解讀
復(fù)制代碼
LoadingProgress() .color(Color.Blue) .height(60) .width(60)

Slider:滑動(dòng)條組件

  1. 滑動(dòng)條組件聲明:
scss
代碼解讀
復(fù)制代碼
Slider(options?:SliderOptions)

滑動(dòng)條組件在創(chuàng)建時(shí),支持傳入 SliderOption 類型的對(duì)象(不傳入則使用默認(rèn)樣式),SliderOption 類型中聲明了一些的滑動(dòng)條組件的UI屬性。

    • min:最小值。
    • max:最大值。
    • value:當(dāng)前默認(rèn)值。
    • setp:滑動(dòng)時(shí)的步長(zhǎng)。
    • style:默認(rèn)OutSet:滑塊在滑條外面。 SliderStyle.inset:滑塊在滑條里面。
    • direction:滑動(dòng)條方向水平或垂直。
    • reverse:是否反轉(zhuǎn)滑動(dòng)條的滑動(dòng)方向。
      false時(shí):水平滑動(dòng)條,左邊為起始位,右邊為終點(diǎn);垂直滑動(dòng)條,下面起始位,上面終點(diǎn)位。
      true時(shí):則相反。
arduino
代碼解讀
復(fù)制代碼
Slider({ min:0,//最小值 max:100,//最大值 value:50,//當(dāng)前值 step:1,//滑動(dòng)步長(zhǎng) style:SliderStyle.OutSet,//默認(rèn)OutSet:滑塊在滑條外面。 另一個(gè)inset:滑塊在滑條里面。 direction:Axis.Horizontal,//滑動(dòng)條水平 或 垂直 reverse:false//是否反向滑動(dòng)。 })

  1. 更多屬性、事件。
    • showTips:是否展示value的百分比提示。
    • blockColor:滑塊的顏色
    • trackThickness:滑動(dòng)條的粗細(xì)
    • onchange((value)=>{}):監(jiān)聽滑塊滑動(dòng)時(shí)值的變更。value就是滑塊當(dāng)前值
javascript
代碼解讀
復(fù)制代碼
.width("90%") .showTips(true)//是否展示value百分比提示 .blockColor("#36d")//滑塊的顏色 .trackThickness(5)//滑動(dòng)條的粗細(xì) .onChange((value)=>{//監(jiān)聽滑塊滑動(dòng)時(shí)值的變更。 //value就是滑??當(dāng)前值 this.mImgWidth=value })

使用資源引用類型

Resource是資源引用類型,用于設(shè)置組件屬性的值。推薦大家優(yōu)先使用Resource類型,將資源文件(字符串、圖片、音頻等)統(tǒng)一存放于resources目錄下,便于開發(fā)者統(tǒng)一維護(hù)。同時(shí)系統(tǒng)可以根據(jù)當(dāng)前配置加載合適的資源,例如,開發(fā)者可以根據(jù)屏幕尺寸呈現(xiàn)不同的布局效果,或根據(jù)語(yǔ)言設(shè)置提供不同的字符串。

例如下面的這段代碼,直接在代碼中寫入了字符串和數(shù)字這樣的硬編碼。

scss
代碼解讀
復(fù)制代碼
Button('登錄', { type: ButtonType.Capsule, stateEffect: true }) .width(300) .height(40) .fontSize(16) .fontWeight(FontWeight.Medium) .backgroundColor('#007DFF')

我們可以將這些硬編碼寫到entry/src/main/resources下的資源文件中。

在string.json中定義Button顯示的文本。

json
代碼解讀
復(fù)制代碼
{ "string": [ { "name": "login_text", "value": "登錄" } ] }

在float.json中定義Button的寬高和字體大小。

css
代碼解讀
復(fù)制代碼
{ "float": [ { "name": "button_width", "value": "300vp" }, { "name": "button_height", "value": "40vp" }, { "name": "login_fontSize", "value": "18fp" } ] }

在color.json中定義Button的背景顏色。

css
代碼解讀
復(fù)制代碼
{ "color": [ { "name": "button_color", "value": "#1890ff" } ] }

然后在Button組件通過“$r('app.type.name')”的形式引用應(yīng)用資源。

  • app代表應(yīng)用內(nèi)resources目錄中定義的資源;
  • type代表資源類型(或資源的存放位置),可以取“color”、“float”、“string”、“plural”、“media”;
  • name代表資源命名,由開發(fā)者定義資源時(shí)確定。
bash
代碼解讀
復(fù)制代碼
Button($r('app.string.login_text'), { type: ButtonType.Capsule }) .width($r('app.float.button_width')) .height($r('app.float.button_height')) .fontSize($r('app.float.login_fontSize')) .backgroundColor($r('app.color.button_color'))

ArkUI-容器組件

Column和Row容器

當(dāng)容器內(nèi)部有多個(gè)組件時(shí),Column(列)會(huì)將內(nèi)部組件從上往下排列,等于安卓垂直方向的LinearLayout;

而Row(行)容器會(huì)將內(nèi)部組件從左向右排列,等于安卓水平方向的LinearLayout。

主軸與交叉軸

已知我們的兩個(gè)容器它們內(nèi)部元素的排列是有方向的,那么它們排列方向的那條中間軸稱之為主軸,與之垂直的稱為交叉軸。我們?nèi)萜髦薪M件的對(duì)齊則是圍繞這兩個(gè)軸來實(shí)現(xiàn)的。

容器提供了以下兩個(gè)方法,用來調(diào)整容器內(nèi)元素的對(duì)齊方式:

屬性方法名說明參數(shù)
justifyContent設(shè)置子元素在主軸方向的對(duì)齊格式FlexAlign枚舉
alignItems設(shè)置子元素在交叉軸方向的對(duì)齊格式Row容器使用VerticalAlign枚舉;Column容器使用HorizontalAlign枚舉。

設(shè)置主軸對(duì)齊方式

枚舉功能
FlexAlign.start主軸方向,內(nèi)部元素默認(rèn)往主軸起始位置靠攏。
FlexAlign.center主軸方向,內(nèi)部元素默認(rèn)往主軸中間位置靠攏。
FlexAlign.end主軸方向,內(nèi)部元素默認(rèn)往主軸終點(diǎn)位置靠攏。
FlexAlign.SpaceBetween主軸方向,頭尾的元素貼近起點(diǎn)/終點(diǎn),其余元素居中平分間距。
FlexAlign.SpaceAround主軸方向,頭尾的元素靠近起點(diǎn)/終點(diǎn)(頭尾元素間距為其他元素間距的一半),其余元素居中平分剩余間距。
FlexAlign.SpaceEvenly主軸方向,所有元素靠近主軸中間,平分間距。

設(shè)置交叉軸對(duì)齊方式

VerticalAlign

因?yàn)镽ow容器內(nèi)部元素是水平排列的,所以交叉軸是垂直的,因此使用VerticalAlign,控制垂直方向的元素排列。

枚舉功能
VerticalAlign.start垂直方向,靠近交叉軸的起始位置。
VerticalAlign.center垂直方向,靠近交叉軸的中間位置。
VerticalAlign.end垂直方向,靠近交叉軸的終點(diǎn)位置。

HorizontalAlign

因?yàn)镃olumn容器內(nèi)部元素是垂直排列的,所以交叉軸是水平的,因此使用HorizontalAlign,控制水平方向的元素排列。

枚舉功能
HorizontalAlign.start水平方向,靠近交叉軸的起始位置。
HorizontalAlign.center水平方向,靠近交叉軸的中間位置。
HorizontalAlign.end水平方向,靠近交叉軸的終點(diǎn)位置。

設(shè)置元素內(nèi)、外邊距

每個(gè)UI組件都支持設(shè)置自身的內(nèi)外邊距。內(nèi)邊距使用padding(),外邊距使用margin()。

scss
代碼解讀
復(fù)制代碼
margin(value: Margin | Length) padding(value: Padding | Length)

參數(shù)說明:

  • Length類型:支持傳入string、number、Resource三種類型。如: "1%",10,r、rawfile方式。
scss
代碼解讀
復(fù)制代碼
.margin(20)//設(shè)置上下左右邊距為20
  • Margin類型:Margin是一個(gè)對(duì)象,它里面有四個(gè)參數(shù):
    • top:上邊距。
    • bottom:下邊距。
    • left:左邊距。
    • right:右邊距。
    • 以上四個(gè)參數(shù)可以選擇性設(shè)置,不設(shè)置則默認(rèn)0。
css
代碼解讀
復(fù)制代碼
.margin({top:20,bottom:20,left:0,right:0})//設(shè)置top、bottom、left、right邊距。 .margin({top:20,bottom:20})//只設(shè)置top、bottom的邊距,其他的不設(shè)置。

blank組件

blan組件是個(gè)空組件,主要用來占位,它會(huì)占滿當(dāng)前父容器主軸方向的空閑位置。

比如我寫了一個(gè)布局:一個(gè)Row容器,內(nèi)部由3個(gè)組件構(gòu)成,分別為返回鍵、標(biāo)題、刷新按鈕;

我想使返回按鈕和標(biāo)題欄居左,而刷新按鈕居右。

此時(shí)則可以在標(biāo)題欄 和 刷新按鈕的中間放置一個(gè)Blank組件,這樣一來,刷新按鈕就被擠到了右側(cè)。

案例:圖片放大縮小頁(yè)面

使用前面學(xué)習(xí)的Ark常用組件來完成圖片放大縮小頁(yè)面的開發(fā)。

效果圖:

功能介紹:

  • 布局使用Column、Row容器;圖片組件使用Image、輸入框使用TextInput、文本顯示使用Text、放大/縮小按鈕使用Button、滑動(dòng)條使用Slider。
  • 當(dāng)修改圖片寬度文字時(shí),調(diào)整Image的寬度使其呈現(xiàn)放大效果,同時(shí)拖動(dòng)條位置也跟隨變化。
  • 當(dāng)點(diǎn)擊放大/縮小按鈕時(shí),Image放大/縮小,同時(shí)拖動(dòng)條與圖片寬度文字也同步更新。
  • 當(dāng)拖動(dòng)Slider時(shí),Image跟隨滑動(dòng)變化,同時(shí)圖片寬度文字同步更新。

完成代碼:Linxy/鴻蒙應(yīng)用開發(fā)入門代碼倉(cāng)庫(kù)

scss
代碼解讀
復(fù)制代碼
@Entry @Component struct Index { @State message: string = 'Hello World' @State mImgWidth: number = 300 //用來修飾變量;標(biāo)記這個(gè)變量為狀態(tài)變量,值變化時(shí)會(huì)觸發(fā)對(duì)應(yīng)的UI刷新。 build() { Row() { Column() { Image($rawfile("gmzr.png"))//添加rawfile文件夾下的資源文件 .width(this.mImgWidth)//組件的寬度綁定mImgWidth .height(400)//高設(shè)置為400vp .interpolation(ImageInterpolation.High)//去除圖片鋸齒 Row() { Text("圖片寬度")//文字文本 TextInput({ placeholder: "請(qǐng)輸入指定寬度",//提示詞,類似hint text: this.mImgWidth.toFixed(0)//獲取mImgWidth的文本,包含小數(shù)點(diǎn)后0位。 }) .type(InputType.Number)//只允許輸入數(shù)字 .onChange((value) => { //輸入文字監(jiān)聽 if (value != this.mImgWidth.toString() && value.length > 0) { this.mImgWidth = Number.parseInt(value) } }) .width(200) } .width("90%") .justifyContent(FlexAlign.SpaceBetween)//主軸對(duì)齊方式:頭尾的元素貼近起點(diǎn)/終點(diǎn),其余元素居中平分間距。 .alignItems(VerticalAlign.Center)//內(nèi)部元素沿交叉軸居中,row容器中交叉軸為垂直,所以這里效果為元素上下居中。 .margin({top:20,bottom:20,left:0,right:0})//設(shè)置容器的外邊距 Row() { Button("放大") .width(80) .height(30) .onClick(() => { //監(jiān)聽點(diǎn)擊事件 if (this.mImgWidth < SLIDER_MAX) { if (this.mImgWidth + 50 > SLIDER_MAX) { this.mImgWidth = SLIDER_MAX } else { this.mImgWidth += 50 } } }) .type(ButtonType.Normal)//按鈕使用默認(rèn)的方形樣式 Button("縮小") .width(80) .height(30) .onClick(() => { if (this.mImgWidth > SLIDER_MIN) { if (this.mImgWidth - 50 < SLIDER_MIN) { this.mImgWidth = SLIDER_MIN } else { this.mImgWidth -= 50 } } }) .type(ButtonType.Normal) }.width("100%")//寬度為父容器的百分百,占滿 .justifyContent(FlexAlign.SpaceEvenly)//主軸方向,所有元素靠近主軸中間,平分間距。 左右居中等間距。 Slider({ min: SLIDER_MIN, //最小值 max: SLIDER_MAX, //最大值 value: this.mImgWidth, //當(dāng)前值 step: 1, //滑動(dòng)步長(zhǎng) style: SliderStyle.OutSet, //默認(rèn)OutSet:滑塊在滑條外面。 另一個(gè)inset:滑塊在滑條里面。 direction: Axis.Horizontal, //滑動(dòng)條水平 或 垂直 reverse: false //是否反向滑動(dòng) }) .width("90%") .showTips(true) //是否展示value百分比提示 .blockColor("#36d") //滑塊的顏色 .trackThickness(5) //滑動(dòng)條的粗細(xì) .onChange((value) => { //監(jiān)聽滑塊滑動(dòng)時(shí)值的變更。 //value就是滑塊當(dāng)前值 this.mImgWidth = value }) } .height('100%') // .justifyContent(FlexAlign.SpaceEvenly) .justifyContent(FlexAlign.Center)//主軸方向居中,這里是Column主軸垂直,即垂直居中。 } .height('100%') } } const SLIDER_MIN = 0; const SLIDER_MAX = 2000; function name(params) { }

布局檢查器

在DevEcoStudio編譯器中,點(diǎn)擊Previewer查看預(yù)覽視圖,再點(diǎn)擊Inspector打開布局檢查功能。

打開布局檢查功能后,就能夠點(diǎn)擊預(yù)覽頁(yè)面的視圖、或者點(diǎn)擊ComponentTree中的item項(xiàng),編譯器會(huì)自動(dòng)幫助我們定位到對(duì)應(yīng)的代碼塊,并展示UI相關(guān)的其他信息及獲取布局結(jié)構(gòu)。

容器內(nèi)元素間距space

Row容器和Column容器都支持設(shè)置內(nèi)部元素間的間距值,用法為:

less
代碼解讀
復(fù)制代碼
Row({space:20}) {...} Coloumn({space:20}) {...}

RelativeContainer相對(duì)布局

RelativeContainer是一個(gè)相對(duì)布局容器,通常用于復(fù)雜場(chǎng)景中元素對(duì)齊的布局。

  • 容器內(nèi)的組件區(qū)分 水平方向 和 垂直方向:
    • 水平方向?yàn)閘eft, middle, right,對(duì)應(yīng)容器的HorizontalAlign.Start, HorizontalAlign.Center, HorizontalAlign.End。
    • 垂直方向?yàn)閠op, center, bottom,對(duì)應(yīng)容器的VerticalAlign.Top, VerticalAlign.Center, VerticalAlign.Bottom。
  • 容器內(nèi)的組件必須設(shè)置ID,如果不設(shè)置ID,那么該組件則不會(huì)被顯示。
  • 容器內(nèi)組件主要通過設(shè)置alignRules屬性來決定位置的擺放規(guī)則:
less
代碼解讀
復(fù)制代碼
RelativeContainer() { Button() .id('ConfigBtn') .alignRules({ left: { anchor: '__container__', align: HorizontalAlign.Start }, top: { anchor: '__container__', align: VerticalAlign.Top }, }) }
  • alignRules函數(shù)的參數(shù)是一個(gè) AlignRuleOption 接口,AlignRuleOption 接口中有六個(gè)屬性,分別是:
    • 水平方向上的:left、middle、right,即左中右。
    • 垂直方向上的:top、center、bottom,即上中下。

它們對(duì)應(yīng)著組件的指定位置的對(duì)齊規(guī)則。

  • AlignRuleOption中的屬性是對(duì)象,它們由兩個(gè)參數(shù)構(gòu)成:
    • anchor:錨點(diǎn),即我們給組件設(shè)置的id,'container'表示指向當(dāng)前組件父容器。
      錨點(diǎn)用于標(biāo)識(shí)當(dāng)前組件的某個(gè)位置是以該錨點(diǎn)對(duì)象作為參照物的。
    • align:對(duì)齊方式,水平方向上是HorizontalAlign,垂直方向上是VerticalAlign,內(nèi)部對(duì)應(yīng)著上中,左中右。

如:left: { anchor: 'container', align: HorizontalAlign.Start },表示當(dāng)前組件的左側(cè)坐標(biāo),以父容器作為參考對(duì)象,對(duì)齊父容器的水平方向起始位置(左側(cè))。

ArkUI-循環(huán)控制/FOREACH

ArkUI中,可以通過使用FOREACH函數(shù)來生成列表視圖。

案例:

上述案例中,是一個(gè)商品列表,實(shí)現(xiàn)邏輯大致為:

  1. 首先抽出單條item的布局。
  2. 定義item所需要的數(shù)據(jù)類型Bean類。
  3. 定義列表,存儲(chǔ)每項(xiàng)Item的數(shù)據(jù)。
  4. 借助foreach循環(huán)函數(shù),根據(jù)傳入數(shù)據(jù),而生成組件并渲染

FOREACH

在ArkUI中,繪制列表需要借助FOREACH函數(shù)。

FOREACH函數(shù)共有三個(gè)入?yún)ⅲ?/p>

  • Array:第一個(gè)參數(shù)是要遍歷的數(shù)據(jù)數(shù)組,即列表的數(shù)據(jù)源。
  • (item:any,index?:number)=>{}:第二個(gè)參數(shù)是函數(shù)回調(diào),在此處進(jìn)行頁(yè)面組件的生成渲染。
  • keyGenerator?:(item:any,index?:number):string:第三個(gè)參數(shù)也是函數(shù)回調(diào),它非常重要,我們要在函數(shù)中為item生成唯一標(biāo)識(shí)符,并作為返回值返回。(唯一標(biāo)識(shí)符,通常在Array數(shù)組內(nèi)部會(huì)有定義好的。)
scss
代碼解讀
復(fù)制代碼
FOREACH( arr:Array,//要遍歷的數(shù)據(jù)數(shù)組 (item:any,index?:number)=>{ //頁(yè)面組件生成的函數(shù)回調(diào) Row(){ Image(item.image) Column(){ Text(item.name) Text(item.price) } } }, keyGenerator?:(item:any,index?:number):string => { //定義每個(gè)item項(xiàng)的ID,必須唯一,用于列表內(nèi)部的渲染判斷 } )

案例:實(shí)現(xiàn)一個(gè)列表

  1. 首先,我們先在組件中寫好item的布局:

繪制的item如下:

scss
代碼解讀
復(fù)制代碼
Row({space:20}) { //Row({space:20}) 表示設(shè)置元素間的主軸的間距為20 Image($rawfile('gmzr.png')) .width(100) .height(100) Column(){ Text("商品名稱") .fontSize(20) .fontColor('#000000') .fontWeight(FontWeight.Bold) Text("商品售價(jià):¥190") .fontSize(20) .fontColor('#ff0000') .fontWeight(FontWeight.Bold) }.alignItems(HorizontalAlign.Start) .justifyContent(FlexAlign.SpaceEvenly) .height(130) }.width('auto') .margin({left:15,top:15,bottom:15}) }

  1. 定義每條Item的所需要數(shù)據(jù)類型的Bean類。
typescript
代碼解讀
復(fù)制代碼
export interface ShopItemBean { _id: number; //商品ID _imageUrl: string; //圖片地址 _name: string; //商名稱 _price: number; //商品價(jià)格 }
  1. 創(chuàng)建列表的數(shù)據(jù)數(shù)組
yaml
代碼解讀
復(fù)制代碼
private items: ShopItemBean[] = [ { _id: 1, _name: '華為p10', _imageUrl: '', _price: 1 }, { _id: 2, _name: '小米1', _imageUrl: '', _price: 2 }, { _id: 3, _name: '華為p12', _imageUrl: '', _price: 3 }, { _id: 4, _name: '華為p13', _imageUrl: '', _price: 4 }, { _id: 5, _name: '華為p14', _imageUrl: '', _price: 5 }, { _id: 6, _name: '華為p15', _imageUrl: '', _price: 6 }, { _id: 7, _name: '華為p16', _imageUrl: '', _price: 7 }, { _id: 8, _name: '華為p17', _imageUrl: '', _price: 8 }, { _id: 9, _name: '華為p18', _imageUrl: '', _price: 9 }, { _id: 10, _name: '華為p19', _imageUrl: '', _price: 10 }, { _id: 11, _name: '華為p20', _imageUrl: '', _price: 11 }, { _id: 12, _name: '華為p21', _imageUrl: '', _price: 12 }, ];
  1. 使用FOREACH,繪制item
typescript
代碼解讀
復(fù)制代碼
ForEach(this.items,(item:ShopItemBean,index:number)=>{ //進(jìn)行item布局的繪制 在此處放入我們第一步驟填寫的Item布局,并且將item的數(shù)據(jù)填入到item中 },(item:ShopItemBean,index?:number):string => { //定義每個(gè)item項(xiàng)的ID,必須唯一,用于列表內(nèi)部的渲染判斷 return item.id.toString() })
  1. 繪制完item后,頁(yè)面布局是滑動(dòng)不了的,還需要添加一個(gè)滑動(dòng)控件;
    首先在FOREACH外面添加一個(gè)容器A,在容器A外部包裹一個(gè)scroll控件就能滑動(dòng)了。
    (因?yàn)閟croll控件內(nèi)只能包裹一個(gè)控件,所以要用一個(gè)容器A來包裹FOREACH的列表item)
scss
代碼解讀
復(fù)制代碼
Scroll() { Column() { FOREACH(....) } }

完整代碼:Linxy/ArkUI實(shí)現(xiàn)列表

scss
代碼解讀
復(fù)制代碼
import { ShopItemBean } from 'ets/bean/ShopItemBean' @Entry @Component struct Index2 { private items: ShopItemBean[] = [ { _id: 1, _name: '華為p10', _imageUrl: '', _price: 1 }, { _id: 2, _name: '小米1', _imageUrl: '', _price: 2 }, { _id: 3, _name: '華為p12', _imageUrl: '', _price: 3 }, { _id: 4, _name: '華為p13', _imageUrl: '', _price: 4 }, { _id: 5, _name: '華為p14', _imageUrl: '', _price: 5 }, { _id: 6, _name: '華為p15', _imageUrl: '', _price: 6 }, { _id: 7, _name: '華為p16', _imageUrl: '', _price: 7 }, { _id: 8, _name: '華為p17', _imageUrl: '', _price: 8 }, { _id: 9, _name: '華為p18', _imageUrl: '', _price: 9 }, { _id: 10, _name: '華為p19', _imageUrl: '', _price: 10 }, { _id: 11, _name: '華為p20', _imageUrl: '', _price: 11 }, { _id: 12, _name: '華為p21', _imageUrl: '', _price: 12 }, ]; build() { Column() { Text("商品列表") .fontSize(30) .fontWeight(FontWeight.Bold) .margin({ left: 20 }) Scroll() { Column() { ForEach(this.items, (item: ShopItemBean, index: number) => { //進(jìn)行item布局的繪制 Row() { Image('https://img0.baidu.com/it/u=3628503530,464378779&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=800') .width(100) .height(100) .borderRadius(20) .interpolation(ImageInterpolation.High) Column() { Text(item._name) .fontSize(20) .fontColor('#000000') .fontWeight(FontWeight.Bold) Text("商品售價(jià):¥" + item._price) .fontSize(20) .fontColor('#ff0000') .fontWeight(FontWeight.Bold) }.alignItems(HorizontalAlign.Start) .justifyContent(FlexAlign.SpaceEvenly) .height(130) .margin({ left: 20 }) } .width('95%') .margin({ top: 15, bottom: 15 }) .padding(15) .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Start) .backgroundColor('#c6c6c6') .borderRadius(20) }, (item: ShopItemBean, index?: number): string => { //定義每個(gè)item項(xiàng)的ID,必須唯一,用于列表內(nèi)部的渲染判斷 return item._id.toString() }) }.width('100%') .alignItems(HorizontalAlign.Center) .padding({ bottom: 70 }) }.width('auto') .height('100%') } .width('100%') .height('100%') .alignItems(HorizontalAlign.Start) .margin({ top: 30 }) } }

ArkUI-List容器組件

上述完成了一個(gè)簡(jiǎn)單的列表頁(yè)面開發(fā),但是它存在局限性,比如說無法滑動(dòng)(需要自己去實(shí)現(xiàn))、沒有組件復(fù)用 等問題。

而List容器是正宗的列表布局容器組件(Android的RecycleView),列表容器具備以下特點(diǎn):

  • 列表項(xiàng)(ListItem)數(shù)量過多超出屏幕后,會(huì)自動(dòng)提供滾動(dòng)功能。
  • 列表項(xiàng)(ListItem)既可以縱向排列,也可以橫向排列。

使用方法:

scss
代碼解讀
復(fù)制代碼
List({space:10}){//列表項(xiàng)的間距 ForEach([1,2,3,4],(item:number)=>{ ListItem(){//ListItem是標(biāo)記,不是容器。 //列表項(xiàng)內(nèi)容,只能包含一個(gè)根組件 Text(item.toString()) .fontColor('#ff00ff') .width('auto') .height('auto') .fontSize(20) } }) }.width('100%') .listDirection(Axis.Vertical)//列表方向:默認(rèn)垂直

使用List容器實(shí)現(xiàn)商品列表頁(yè)面:

scss
代碼解讀
復(fù)制代碼
import { ShopItemBean } from 'ets/bean/ShopItemBean' @Entry @Component struct Index3 { private items: ShopItemBean[] = [ { _id: 1, _name: '華為p10', _imageUrl: '', _price: 1 }, { _id: 2, _name: '小米1', _imageUrl: '', _price: 2 }, { _id: 3, _name: '華為p12', _imageUrl: '', _price: 3 }, { _id: 4, _name: '華為p13', _imageUrl: '', _price: 4 }, { _id: 5, _name: '華為p14', _imageUrl: '', _price: 5 }, { _id: 6, _name: '華為p15', _imageUrl: '', _price: 6 }, { _id: 7, _name: '華為p16', _imageUrl: '', _price: 7 }, { _id: 8, _name: '華為p17', _imageUrl: '', _price: 8 }, { _id: 9, _name: '華為p18', _imageUrl: '', _price: 9 }, { _id: 10, _name: '華為p19', _imageUrl: '', _price: 10 }, { _id: 11, _name: '華為p20', _imageUrl: '', _price: 11 }, { _id: 12, _name: '華為p21', _imageUrl: '', _price: 12 }, ]; build() { Column() { Text("商品列表") .fontSize(30) .fontWeight(FontWeight.Bold) .margin({ left: 20 }) List({ space: 10 }) { //列表項(xiàng)的間距 ForEach(this.items, (item: ShopItemBean) => { ListItem() { //ListItem是標(biāo)記,不是容器。 //列表項(xiàng)內(nèi)容,只能包含一個(gè)根組件 //進(jìn)行item布局的繪制 Row({ space: 20 }) { Image('https://img0.baidu.com/it/u=3628503530,464378779&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=800') .width(100) .height(100) .borderRadius(20) .interpolation(ImageInterpolation.High) Column() { Text(item._name) .fontSize(20) .fontColor('#000000') .fontWeight(FontWeight.Bold) Text("商品售價(jià):¥" + item._price) .fontSize(20) .fontColor('#ff0000') .fontWeight(FontWeight.Bold) }.alignItems(HorizontalAlign.Start) .justifyContent(FlexAlign.SpaceEvenly) .height(130) } .width('95%') .margin({ top: 15, bottom: 15 }) .padding(15) .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Start) .backgroundColor('#c6c6c6') .borderRadius(20) } }) }.width('100%') .layoutWeight(1)//注意,使用這個(gè)方式來配置好list組件的高度,如果高度沒配置好,可能會(huì)出現(xiàn)滑動(dòng),顯示不完整等問題。 //listDirection():設(shè)置List列表內(nèi)部排列方向,參數(shù)是 Axis 枚舉:默認(rèn)垂直; // Vertical(默認(rèn)值):子組件ListItem在List容器組件中呈縱向排列。Horizontal:子組件ListItem在List容器組件中呈橫向排列。 .listDirection(Axis.Vertical) .alignListItem(ListItemAlign.Center)//列表內(nèi)item項(xiàng)交叉軸居中 }.width('100%') .alignItems(HorizontalAlign.Center) } }

設(shè)置列表分割線

List組件子組件ListItem之間默認(rèn)是沒有分割線的,部分場(chǎng)景子組件ListItem間需要設(shè)置分割線,這時(shí)候可以使用List組件的divider屬性。
divider屬性包含四個(gè)參數(shù):

  • strokeWidth: 分割線的線寬。
  • color: 分割線的顏色。
  • startMargin:分割線距離列表側(cè)邊起始端的距離。
  • endMargin: 分割線距離列表側(cè)邊結(jié)束端的距離。

scss
代碼解讀
復(fù)制代碼
List({ space: 10 }) { //列表項(xiàng)的間距 ForEach(this.items, (item: ShopItemBean) => { ListItem() { //ListItem是標(biāo)記,不是容器。 ShopItemCard(item) } }) }.width('100%') //設(shè)置分割線 .divider({strokeWidth:2,startMargin:5,endMargin:5,color:"#ff00ff"})

List列表滾動(dòng)事件監(jiān)聽

List組件提供了一系列事件方法用來監(jiān)聽列表的滾動(dòng),我們可以根據(jù)需要,監(jiān)聽這些事件來做一些操作:

  • onScroll:列表滑動(dòng)時(shí)觸發(fā),返回值scrollOffset為滑動(dòng)偏移量,scrollState為當(dāng)前滑動(dòng)狀態(tài)。
  • onScrollIndex:列表滑動(dòng)時(shí)觸發(fā),返回值分別為滑動(dòng)起始位置索引值與滑動(dòng)結(jié)束位置索引值。
  • onReachStart:列表到達(dá)起始位置時(shí)觸發(fā)。
  • onReachEnd:列表到底末尾位置時(shí)觸發(fā)。
  • onScrollStop:列表滑動(dòng)停止時(shí)觸發(fā)。
typescript
代碼解讀
復(fù)制代碼
List({ space: 10 }) { ForEach(this.arr, (item) => { ListItem() { Text(`${item}`) ... } }, item => item) } //列表滑動(dòng)時(shí)觸發(fā),返回值分別為滑動(dòng)起始位置索引值與滑動(dòng)結(jié)束位置索引值。 .onScrollIndex((firstIndex: number, lastIndex: number) => { console.info('first' + firstIndex) console.info('last' + lastIndex) }) //列表滑動(dòng)時(shí)觸發(fā),返回值scrollOffset為滑動(dòng)偏移量,scrollState為當(dāng)前滑動(dòng)狀態(tài)。 .onScroll((scrollOffset: number, scrollState: ScrollState) => { console.info('scrollOffset' + scrollOffset) console.info('scrollState' + scrollState) }) // 列表到達(dá)起始位置時(shí)觸發(fā)。 .onReachStart(() => { console.info('onReachStart') }) // 列表到底末尾位置時(shí)觸發(fā)。 .onReachEnd(() => { console.info('onReachEnd') }) // onScrollStop:列表滑動(dòng)停止時(shí)觸發(fā)。 .onScrollStop(() => { console.info('onScrollStop') })

Grid組件的使用

Grid組件簡(jiǎn)介

Grid組件為網(wǎng)格容器,是一種網(wǎng)格列表,由“行”和“列”分割的單元格所組成,通過指定“項(xiàng)目”所在的單元格做出各種各樣的布局。Grid組件一般和子組件GridItem一起使用,Grid列表中的每一個(gè)條目對(duì)應(yīng)一個(gè)GridItem組件。

使用ForEach渲染網(wǎng)格布局

和List組件一樣,Grid組件也可以使用ForEach來渲染多個(gè)列表項(xiàng)GridItem,我們通過下面的這段示例代碼來介紹Grid組件的使用。

scss
代碼解讀
復(fù)制代碼
@Entry @Component struct GridExample { // 定義一個(gè)長(zhǎng)度為16的數(shù)組 private arr: string[] = new Array(16).fill('').map((_, index) => `item ${index}`); build() { Column() { Grid() { ForEach(this.arr, (item: string) => { GridItem() { Text(item) .fontSize(16) .fontColor(Color.White) .backgroundColor(0x007DFF) .width('100%') .height('100%') .textAlign(TextAlign.Center) } }, item => item) } .columnsTemplate('1fr 1fr 1fr 1fr') .rowsTemplate('1fr 1fr 1fr 1fr') .columnsGap(10) .rowsGap(10) .height(300) } .width('100%') .padding(12) .backgroundColor(0xF1F3F5) } }

示例代碼中創(chuàng)建了16個(gè)GridItem列表項(xiàng)。同時(shí)設(shè)置columnsTemplate的值為'1fr 1fr 1fr 1fr',表示這個(gè)網(wǎng)格為4列,將Grid允許的寬分為4等分,每列占1份;rowsTemplate的值為'1fr 1fr 1fr 1fr',表示這個(gè)網(wǎng)格為4行,將Grid允許的高分為4等分,每行占1份。這樣就構(gòu)成了一個(gè)4行4列的網(wǎng)格列表,然后使用columnsGap設(shè)置列間距為10vp,使用rowsGap設(shè)置行間距也為10vp。示例代碼效果圖如下:

上面構(gòu)建的網(wǎng)格布局使用了固定的行數(shù)和列數(shù),所以構(gòu)建出的網(wǎng)格是不可滾動(dòng)的。然而有時(shí)候因?yàn)閮?nèi)容較多,我們通過滾動(dòng)的方式來顯示更多的內(nèi)容,就需要一個(gè)可以滾動(dòng)的網(wǎng)格布局。我們只需要設(shè)置rowsTemplate和columnsTemplate之間的一個(gè)即可,另一個(gè)不設(shè)置。

如:將示例代碼中GridItem的高度設(shè)置為固定值,例如100;僅設(shè)置columnsTemplate屬性,不設(shè)置rowsTemplate屬性,就可以實(shí)現(xiàn)Grid列表的滾動(dòng):

scss
代碼解讀
復(fù)制代碼
Grid() { ForEach(this.arr, (item: string) => { GridItem() { Text(item) .height(100) ... } }, item => item) } .columnsTemplate('1fr 1fr 1fr 1fr')//將網(wǎng)格分為4行,每行占容器一等份的長(zhǎng)度 .columnsGap(10)//設(shè)置列間距為10vp .rowsGap(10)//設(shè)置行間距 .height(300)//固定高度

此外,Grid像List一樣也可以使用onScrollIndex來監(jiān)聽列表的滾動(dòng)。

ArkUI-自定義組件

自定義組件聲明

自定義組件大家并不陌生;在ArkUI中,自定義組件的實(shí)現(xiàn)是一個(gè)struct結(jié)構(gòu)體+@Component裝飾器組合,就完成了聲明。

less
代碼解讀
復(fù)制代碼
@Component struct Index3 { }

使用自定義組件

比如我完成了一個(gè)名為 Header 的自定義組件,那么我在代碼中使用就是 直接使用 Header() 來使用這個(gè)組件:

自定義組件案例:封裝標(biāo)題欄自定義組件

  1. 首先編寫標(biāo)題欄的item
scss
代碼解讀
復(fù)制代碼
Row(){ Image($r('app.media.back')) .width(40) .height(40) .interpolation(ImageInterpolation.High) Text("標(biāo)題") .fontSize(30) .fontColor('#000000') .fontWeight(FontWeight.Bold) .margin({left:30}) Blank() Image($r('app.media.refresh')) .width(40) .height(40) }.justifyContent(FlexAlign.Start) .width("100%") .alignItems(VerticalAlign.Center) .padding({left:20,top:20,right:20,bottom:20})

  1. 創(chuàng)建一個(gè)自定義View:CommonTitleBar
scss
代碼解讀
復(fù)制代碼
/** * 標(biāo)題欄組件 */ @Component struct CommonTitleBar{ build(){ //..放置寫好的item布局 } }
  1. 放置第一步中寫好的item布局代碼
scss
代碼解讀
復(fù)制代碼
/** * 標(biāo)題欄組件 */ @Component export struct CommonTitleBar{ build(){ Row(){ Image($r('app.media.back')) .width(40) .height(40) .interpolation(ImageInterpolation.High) Text("標(biāo)題") .fontSize(30) .fontColor('#000000') .fontWeight(FontWeight.Bold) .margin({left:30}) Blank() Image($r('app.media.refresh')) .width(40) .height(40) }.justifyContent(FlexAlign.Start) .width("100%") .alignItems(VerticalAlign.Center) .padding({left:20,top:20,right:20,bottom:20}) } }
  1. 給自定義View設(shè)置所需的成員參數(shù),并配置構(gòu)造函數(shù),使用。
scss
代碼解讀
復(fù)制代碼
@State private _title: string = ""; constructor(_title: string) { super(); this._title = _title } .... Text(this._title) .fontSize(30) .fontColor('#000000') .fontWeight(FontWeight.Bold) .margin({ left: 30 }) ....
  1. 在主頁(yè)使用CommonTitleBar組件
scss
代碼解讀
復(fù)制代碼
import { CommonTitleBar } from '../widget/CommonTitleBar';//導(dǎo)入組件 build() { Column() { CommonTitleBar({_title:'商品列表'}) .margin(10)//所有的自定義組件也是添加樣式函數(shù) list.... } }
  1. 這樣一個(gè)公共的標(biāo)題欄組件就完成了。

自定義構(gòu)建函數(shù)及案例:封裝ListItem布局

接下來我們還想將商品列表的ListItem也進(jìn)行封裝,那么可以繼續(xù)使用自定義組件的方式來封裝;但是,我們還有一種更方便的方法,自定義構(gòu)建函數(shù)。

  1. 在全局中,使用@Builder來標(biāo)識(shí)自定義構(gòu)建函數(shù),自定義構(gòu)建函數(shù)建議使用大寫字母開頭,因?yàn)樗部梢员焕斫獬梢粋€(gè)匿名的自定義View組件
less
代碼解讀
復(fù)制代碼
@Builder function ShopItemCard(){...}
  1. 在函數(shù)中,完成聲明式UI的聲明:將我們先前寫的ListItem的布局復(fù)制過來。
scss
代碼解讀
復(fù)制代碼
//全局自定義構(gòu)建函數(shù) @Builder function ShopItemCard(){ //列表項(xiàng)內(nèi)容,只能包含一個(gè)根組件 //進(jìn)行item布局的繪制 Row({ space: 20 }) { Image('https://img0.baidu.com/it/u=3628503530,464378779&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=800') .width(100) .height(100) .borderRadius(20) .interpolation(ImageInterpolation.High) Column() { Text(item._name) .fontSize(20) .fontColor('#000000') .fontWeight(FontWeight.Bold) Text("商品售價(jià):¥" + item._price) .fontSize(20) .fontColor('#ff0000') .fontWeight(FontWeight.Bold) }.alignItems(HorizontalAlign.Start) .justifyContent(FlexAlign.SpaceEvenly) .height(130) } .width('95%') .margin({ top: 15, bottom: 15 }) .padding(15) .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Start) .backgroundColor('#c6c6c6') .borderRadius(20) }
  1. 此時(shí)發(fā)現(xiàn)函數(shù)中 item 報(bào)紅,因?yàn)槟貌坏絠tem數(shù)據(jù),所以增加一個(gè)形參:
less
代碼解讀
復(fù)制代碼
@Builder function ShopItemCard(item:ShopItemBean){...}
  1. 在List組件中,調(diào)用自定義構(gòu)建函數(shù):
scss
代碼解讀
復(fù)制代碼
List({ space: 10 }) { //列表項(xiàng)的間距 ForEach(this.items, (item: ShopItemBean) => { ListItem() { //ListItem是標(biāo)記,不是容器。 //此處調(diào)用自定義構(gòu)建函數(shù) ShopItemCard(item) } }) }
  1. 這樣便完成了ListItem的UI繪制。

局部自定義構(gòu)建函???

我們剛才的實(shí)例中自定義構(gòu)建函數(shù)是聲明在全局的,即全局自定義構(gòu)建函數(shù),這樣的話其他文件也能使用它。

如果只想給將自定義構(gòu)建函數(shù)放在類中去使用,不給外部使用,那么就得使用局部自定義構(gòu)建函數(shù)。即 把函數(shù)的聲明&定義放在class中;但是請(qǐng)注意,在class類中的函數(shù)不可以使用function關(guān)鍵字,所以在class中function關(guān)鍵字是要省略的,即:

less
代碼解讀
復(fù)制代碼
class MyClass(){ //局部自定義構(gòu)建函數(shù) @Builder ShopItemCard(item:ShopItemBean){...} }

注意:調(diào)用局部自定義構(gòu)建函數(shù)時(shí),添加 this.前綴,因?yàn)轭愔械某蓡T,必須使用this來指向。

自定義公共樣式函數(shù)

自定義公共樣式 與 自定義組件的構(gòu)建函數(shù)大差不差,只是將 @Builder 裝飾器 更換為了 @Styles。

自定義公共樣式函數(shù)主要是封裝公共的樣式,給其他View使用。

定義:如下定義了一個(gè)公共樣式函數(shù),并將width和height設(shè)置為100%

less
代碼解讀
復(fù)制代碼
//自定義公共樣式函數(shù) @Styles function mathStyleWH(){ .width('100%') .height('100%') }

使用:直接在組件的尾部調(diào)用我們的mathStyleWH()函數(shù),等于Column組件調(diào)用了width('100%') 和 height('100%')兩個(gè)函數(shù)。這玩意像宏定義。

scss
代碼解讀
復(fù)制代碼
Column() .mathStyleWH()

注意

  • 自定義公共樣式函數(shù)也分 全局 和 局部,與自定義構(gòu)建函數(shù)一致。
  • 自定義公共樣式函數(shù),默認(rèn)情況下只能修改所有組件的公共函數(shù),即通用的屬性方法。
  • 如果需要修改某個(gè)組件的特定屬性,如Text組件的fontsize屬性,那么就需要使用@Extend裝飾器,表示繼承該View。
java
代碼解讀
復(fù)制代碼
//指定父類為Text組件,設(shè)置其的特定屬性。 @Extend(Text) function setFontColor(){ .fontColor('#00ff00') }

總結(jié)

  • 自定義組件有兩種方式:
    • 自定義View
      @Component Struct View
    • 自定義構(gòu)建函數(shù)
      @Builder funName(){...}
      自定義構(gòu)建函數(shù)又分為:全局和局部函數(shù),作用域不同。
  • 自定義樣式函數(shù):@Styles functionName(){...}
    自定義樣式函數(shù)用來集中控制公共樣式,便于后期對(duì)樣式統(tǒng)一的修改。
    @Styles裝飾器只能修改所有組件公共的屬性,如果想使用特定組件的專用屬性,可以使用@Extend()繼承。
    @Styles 裝飾器 支持修飾全局和局部函數(shù),而@Extend 裝飾器只允許修飾全局函數(shù)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多