HDC2021技術分論壇:ArkUI 3.0讓多裝置開發更簡單!

語言: CN / TW / HK

作者:wanglei,華為UI程式設計框架技術專家

HarmonyOS自誕生以來,就是為滿足分散式多裝置應用場景而設計的,大到智慧屏、車機、平板,小到手機、手錶。在多裝置場景下進行應用UI介面開發,面臨新的困難與挑戰,如下圖所示:

1.jpg

​圖1 多裝置開發的挑戰

為了使UI介面在色彩風格、螢幕尺寸、互動方式和元件功能等差異下仍能夠正常顯示,無疑需要開發人員花費大量精力在UI適配。開發人員常常需要實現多套介面佈局(甚至多套工程),來滿足不同裝置間的設計差異。即使頁面差異不大,也需要進行多裝置測試,多次打包編譯在裝置或者模擬器上執行檢視效果。後期維護過程中也需要不斷檢視不同裝置下的相容性,這些都極大地增加了應用開發者的工作量。

為了解決上述問題,簡化開發者在多裝置上的開發除錯成本,我們提出了一次開發多端部署的設計理念,實現通過一套工程程式碼,一次開發上架,即可按需部署到不同裝置。為了實現這一目標,我們從Harmony系統能力、ArkUI 3.0框架能力和開發工具能力三個方面,為開發者提供了多種適配方法和能力。下面將一一為大家介紹。

一、HarmonyOS系統能力

首先介紹一下系統層面提供的能力。系統能力無需開發者進行頁面調整,也無需進行業務邏輯調整,僅通過增加簡單的幾行配置描述,即可由系統進行多裝置適配。系統能力與開發正規化無關,因此在新的UI程式設計框架下仍可使用。下面我們依次介紹兩種系統能力:模擬小窗和平行視界。

1. 模擬小窗

模擬小窗是最常用也是最簡單的一種多裝置適配方式,通過利用系統的懸浮窗能力,將低解析度的應用,以懸浮視窗的形式在高解析度螢幕上進行顯示。常見的使用場景是手機應用在平板或PC上執行的場景,如下圖所示:

2.jpg

圖2 模擬小窗

模擬小窗的使用方式非常簡單,只需在專案中config.json檔案中增加兩條描述,分別配置好應用的目標裝置型別和響應的視窗尺寸,即可將低解析度的應用執行在高解析度裝置上。示例程式碼如下:

```

{ “app”: { ... “smartWindowSize”:“360*640”, “smartWindowDeviceType”: [ “tablet” ] }, ... }複製 ```

這種使用方式能夠良好地保證我們應用的展示效果和原始平臺效果是一致的,無需開發者進行額外的介面的適配。但是這種方式也有侷限,最顯著的問題就是沒有辦法利用全部高解析度的螢幕,整個螢幕內展示的資料量沒有因螢幕解析度的增加而增大,造成了螢幕上空間的浪費。為解決此問題,系統提供了另一種適配方案——平行視界。

2. 平行視界

系統針對摺疊屏、平板裝置提供了平行視界的能力,藉助分屏顯示的思想,將螢幕分為左右兩個部分,分別顯示應用相關聯的兩個頁面內容。這樣每個區域都能夠保持良好的介面顯示效果,也增加了螢幕內的有效資料量,良好地利用了螢幕顯示區域。常用於新聞、購物類的場景,將相關的兩個頁面同時顯示,如下圖所示:

3.jpg

圖3 平行視界

使用平行視界時,首先需要在config.json檔案中配置metaData,宣告支援平行視界。同時,還需要增加easygo.json檔案進行頁面路由關係配置,指導系統進行分屏顯示。

平行視界的詳細使用說明,可參考官網:

https://developer.harmonyos.com/cn/docs/documentation/doc-guides/multi-device-ui-app-multiplier-guidelines-0000001135848428

二、ArkUI 3.0框架能力

上述兩種是通過配置即可實現的多端適配方案,使用簡單,但是使用場景比較受限。為了更加精準地適配多裝置介面,ArkUI 3.0框架提供了媒體查詢、多型控制元件、原子佈局和柵格系統,方便開發者選擇合適的能力進行UI介面構建。

1. 媒體查詢

媒體查詢是CSS提供的標準能力,是響應式Web設計的關鍵部分。在新的UI正規化中仍保留了此能力,作為最基礎的UI響應式設計能力。在新的UI正規化中,通過API介面方式對外提供媒體查詢能力,可以探查的範圍包括頁面尺寸、裝置解析度、螢幕方向、頁面寬高比、螢幕尺寸、裝置型別、螢幕型別和主題模式。開發者可以根據不同的查詢結果,進行定製化處理。比如:當螢幕方向變化時,可以調整介面內佈局樣式和元件顯示效果;也可以根據裝置型別不同,控制組件的顯示和隱藏;並且當查詢狀態發生變化時,提供事件通知。

4.jpg

圖4 媒體查詢

2. 多型元件

UI介面構建離不開元件的使用。ArkUI 3.0框架為開發者提供了多型元件,通過元件將不同裝置的樣式風格和互動方式進行封裝,替開發者完成大部分適配相關工作。開發者在使用多型元件時,無需考慮裝置差異,只需關注功能實現即可。

下面通過一個示例來看看,相同的一套開發程式碼在手機、智慧屏和車機上展示的不同效果。

5.jpg

圖5 多型元件

示例程式碼如下:

```

Column() { Text("手機 / 平板") .margin({top: 150}) Button("普通按鈕") .margin({top: 40}) .onClick(() => { AlertDialog.show({title: '發現新版本', message: '當前使用移動資料網路,將消耗 XXX MB流量,是否更新', primaryButton: { value: '立即更新', action: () => {} }, secondaryButton: { value: '以後再說', action: () => {} }}) }) }複製 ```

產品設計人員常常不滿足於使用系統預設樣式,希望能夠針對不同的平臺使用自定義的風格樣式。為了避免開發者逐個元件地進行樣式調整,ArkUI 3.0框架將元件樣式相關設定資訊(如顏色、尺寸、圓角弧度、內容文字等)抽象出來形成了一個引數表,按照引數名稱和引數值的方式進行對映。UI元件樣式屬性值都來自這張引數表,開發者和設計人員只需調整引數值,即可調整元件的顯示效果。

3. 原子佈局

多裝置間差異最大的還是螢幕的解析度,差異解析度適配離不開自適應佈局的能力。針對常見的開發場景,我們提煉了七種原子佈局能力。這些佈局可以獨立使用,也可多種佈局疊加使用。下面我們依次介紹這七種原子佈局能力:

(1)折行佈局: 常用於橫豎屏適配或手機向平板切換的場景。比如,豎直方向空間減少,但是水平方向上顯示區域增加,這時可考慮使用折行佈局,將豎直方向的排版變成水平方向。

6.jpg

圖6 折行佈局

折行佈局利用了Flex佈局的折行能力實現,配合佈局約束設定,即可實現折行排布效果。示例程式碼如下:

```

Flex({direction: FlexDirection.Column, wrap: FlexWrap.Wrap}) { Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) { Text("First Content") .fontColor(Color.White) .fontSize(30) } .constraintSize({minWidth: '50%', minHeight: '50%', maxWidth: 400}) .backgroundColor(Color.Gray) Flex({justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) { Text("Second Content") .fontSize(30) .fontColor(Color.White) } .constraintSize({minWidth: '50%', minHeight: '50%', maxWidth: 400}) .backgroundColor('rgb(207, 171, 103)')複製 ```

(2)均分佈局: 常用於內容數量固定、均分顯示的場景,比如工具欄、底部選單欄等。

7.jpg

圖7 均分佈局

示例程式碼如下:

```

@Entry @Component struct Index { build() { Flex({direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceEvenly}) { Text('Hello') .fontSize(20) .borderColor(Color.Red) .borderWidth(1) Text('World') .fontSize(20) .borderColor(Color.Red) .borderWidth(1) Text('Ark') .fontSize(20) .borderColor(Color.Red) .borderWidth(1) Text('UI') .fontSize(20) .borderColor(Color.Red) .borderWidth(1) } .width('100%') .height('100%') } }複製 ```

僅需配置為FlexAlign.SpaceEvenly模式,即可在Flex元件中將內容均分顯示。

(3)隱藏佈局: 是一種比較高階的佈局方式,常用於解析度變化較大,且不同解析度下顯示內容有所差異的場景。主要思想是通過增加或減少顯示內容,來保持最佳的顯示效果。比如媒體播放控制器,在寬屏場景可以完整顯示全部控制項(包含播放、暫停、上一首、下一首、快進、快退,可能還有點贊和收藏按鈕等),而在低解析度場景只保留部分控制項(比如播放、暫停、上一首、下一首按鈕)。

8.jpg

圖8 隱藏佈局

隱藏佈局使用方式非常簡單,只需通過displayPriority方法設定顯示優先順序,具有相同優先順序的元素會同時顯示或隱藏。在進行佈局計算時,會根據當前可用空間,計算當前可顯示元件進行顯示。示例程式碼如下:

```

Row({space: 10}) { Text('1') .width(100) .textAlign(TextAlign.Center) .fontSize(40) .backgroundColor(Color.Red) .displayPriority(2) Text('2') .width(100) .fontSize(40) .textAlign(TextAlign.Center) .backgroundColor(Color.Red) .displayPriority(1) Text('3') .width(100) .textAlign(TextAlign.Center) .fontSize(40) .backgroundColor(Color.Red) .displayPriority(3) Text('4') .width(100) .textAlign(TextAlign.Center) .fontSize(40) .backgroundColor(Color.Red) .displayPriority(1) Text('5') .width(100) .textAlign(TextAlign.Center) .fontSize(40) .backgroundColor(Color.Red) .displayPriority(2) }複製 ```

(4)佔比佈局: 是一種很常見的佈局,就是根據容器尺寸按照比例進行顯示。

9.jpg

圖9 佔比佈局

通過設定百分比尺寸,即可實現比例調整。示例程式碼如下:

```

@Entry @Component struct Index { build() { Row() { Text('Hello') .fontSize(20) .width('50%') .backgroundColor(Color.Red) Text('World') .fontSize(20) .width('20%') .backgroundColor(Color.Yellow) Text('Ark') .fontSize(20) .width('15%') .backgroundColor(Color.Green) Text('UI') .fontSize(20) .width('15%') .backgroundColor(Color.Gray) } .width('100%') .height('100%') } }複製 ```

(5)拉伸縮放佈局: 元件尺寸跟隨父容器尺寸變化,產生拉伸或縮放的展示效果。

10.jpg

圖10 拉伸縮放佈局

通過設定相對容器的比例,實現拉伸或縮放的展示效果。示例程式碼如下:

```

Row() { Image($r('app.media.background')) .objectFit(ImageFit.Fill) .width('100%') .height('100%') }複製 ```

(6)固定寬高比佈局: 在拉伸縮放時保持自身寬高比,通常用於圖片縮放場景中,可保持圖片顯示效果正常,避免圖片被拉長或壓癟,引起顯示失真。 

11.jpg

圖11 固定寬高比佈局

通過設定寬高比,保持按照固定寬高比進行拉伸顯示,保障圖片不會產生變形。示例程式碼如下:

```

Row() { Image($r('app.media.background')) .objectFit(ImageFit.Fill) .width('100%') .height('100%') .aspectRatio(1.2) }複製 ```

(7)延伸佈局: 根據尺寸調整內容顯示數量,主要是通過像列表這樣的能力來實現。

12.jpg

圖12 延伸佈局

根據寬度不同,顯示不同數量的內容,並且可以通過滑動操作,顯示出更多內容。示例程式碼如下:

```

@Entry @Component struct Index { private data: string[] = ['Hello', 'World', 'Ark', 'UI', 'This', 'Is', 'Layout', 'Demo'] build() { Flex({direction:FlexDirection.Column, justifyContent: FlexAlign.Center}) { List({space: 10}) { ForEach(this.data, (item) => { ListItem() { Text(item) .fontSize(20) .width(80) }.height(80) .backgroundColor(Color.Red) }) } .listDirection(Axis.Horizontal) .width('100%') .height(100) } .width('100%') .height('100%') } }複製 ```

此示例通過List作為佈局容器,進行內容線性排布,並支援滑動響應。

4. 柵格系統

ArkUI 3.0框架還提供了完整的柵格系統。所謂柵格系統是來自UX設計中的柵格設計,將螢幕寬度按照不同數量的柵格劃分為不同的列,元件的尺寸佔用一個或多個柵格。採用這種方式進行設計的佈局系統,稱之為柵格系統。使用柵格系統,可以遮蔽螢幕解析度的差異,在不同解析度的螢幕上保持顯示內容的相對尺寸一致。

常見的柵格系統有8柵格系統和12柵格系統,而我們提供的是動態柵格系統,可以根據不同的螢幕尺寸,動態地調整柵格數量。使用動態柵格系統時,不同解析度的裝置使用不同的柵格配置,比如:手機豎屏採用4柵格系統,手機橫屏和摺疊屏採用8柵格系統,大屏採用12柵格系統。

13.jpg

圖13 動態柵格系統

為了方便開發者使用,ArkUI 3.0框架提供了柵格佈局容器GridContainer。下面我們來看一個示例,程式碼如下:

```

Stack() { GridContainer({sizeType: SizeType.Auto}) { Row() { Button('OK') .fontSize(30) .gridSpan(2) .useSizeType({lg: 4}) } } }複製 ```

柵格佈局容器可以設定為固定柵格數,也可以設定為Auto模式。此示例採用的是Auto模式,柵格佈局容器會根據寬度動態調整柵格數量。同時通過useSizeType屬性方法,可以設定在不同柵格模式下,元件佔用的柵格數量。比如:“.useSizeType({lg: 4})”表示在large柵格系統(即12柵格系統)中,Button元件寬度佔用4柵格顯示。

因此,此示例在手機和平板上的顯示效果如下:

14.jpg

圖14 顯示效果

三、開發工具能力

除了上面的系統能力和ArkUI 3.0框架能力外,我們還從開發工具(DevEco Studio)方面,為開發者提供了各種各樣的開發模板,以及多裝置預覽等能力,減少開發者的開發除錯成本,提升開發效率。

1. 開發模板

開發模板主要包括工程模板和卡片模板。

  • 工程模板: DevEco Studio預置了豐富的工程模板,可以根據工程嚮導輕鬆建立適應於各類裝置的工程,並自動生成對應的程式碼和資源模板。建立工程時,開發者可以挑選合適的工程模板。
  • 卡片模板: DevEco Studio提供了多種型別的卡片模板,開發者可以根據需要展示的資訊型別靈活選擇模板,快速構建服務卡片。

15.png

圖15 工程模板和卡片模板

2. 多裝置預覽

DevEco Studio還支援多裝置預覽能力,開發者可以在同一視窗中,同時檢視多種裝置下UI介面的展示效果。預覽器與真機裝置採用相同渲染引擎和UI框架,可以最大程度地做到預覽效果與真機執行效果的一致。以下影片展示了多裝置預覽能力:

影片 gif.gif

感興趣的小夥伴,可以從官網下載和體驗DevEco Studio新版本:https://developer.harmonyos.com/cn/develop/deveco-studio

四、結束語

實現完美的一次開發多端部署效果,離不開開發者的參與。UI開發框架和系統在實現一次開發多端部署的過程中進行了初步的探索,也期待開發者能反饋更多的多裝置UI開發過程中的痛點,以及期待系統框架提供的能力。歡迎開發者和我們一起,在開源社群將一次開發多端部署的能力豐富起來!

cke_542.gif​​​

掃碼新增開發者小助手微信

獲取更多HarmonyOS開發資源和開發者活動資訊