從一個例子開始
本章通過一個天氣應(yīng)用,介紹一多應(yīng)用的整體開發(fā)過程,包括UX設(shè)計、工程管理及調(diào)試、頁面開發(fā)等。
UX設(shè)計
本示例中的天氣應(yīng)用包含主頁、管理城市和添加城市三個頁面,其中主頁中又包含菜單和更新間隔兩個彈窗,基本業(yè)務(wù)邏輯如下所示。
“一多”建議從最初的設(shè)計階段開始就拉通多設(shè)備綜合考慮。考慮實際智能終端設(shè)備種類繁多,設(shè)計師無法針對每種具體設(shè)備各自出一份UX設(shè)計圖?!耙欢唷苯ㄗh從設(shè)備屏幕寬度的維度,將設(shè)備劃分為四大類。設(shè)計師只需要針對這四大類設(shè)備做設(shè)計,而無需關(guān)心具體的設(shè)備形態(tài)。
設(shè)備類型 | 屏幕寬度(vp) |
---|---|
超小設(shè)備 | [0, 320) |
小設(shè)備 | [320, 600) |
中設(shè)備 | [600, 840) |
大設(shè)備 | [840, +∞) |
說明:
開發(fā)前請熟悉鴻蒙開發(fā)指導(dǎo)文檔:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
]
- vp是virtual pixel(虛擬像素)的縮寫,是常用的長度單位,詳見[視覺基礎(chǔ)]小節(jié)中的介紹。
- 此處基于設(shè)備屏幕寬度劃分不同設(shè)備是為了方便理解。通常智能設(shè)備上的應(yīng)用都是以全屏的形式運行,但隨著移動技術(shù)的發(fā)展,當(dāng)前部分智能設(shè)備支持應(yīng)用以自由窗口模式運行(即用戶可以通過拖拽等操作自由調(diào)整應(yīng)用運行窗口的尺寸),故以應(yīng)用窗口尺寸為基準(zhǔn)進(jìn)行劃分更為合適,本文后續(xù)的響應(yīng)式布局章節(jié)中將詳細(xì)介紹相關(guān)內(nèi)容。
- OpenHarmony當(dāng)前僅有默認(rèn)設(shè)備和平板兩種設(shè)備形態(tài),IDE在創(chuàng)建OpenHarmony工程時也僅可以選擇默認(rèn)設(shè)備和平板。隨著演進(jìn),其支持的設(shè)備形態(tài)會不斷豐富,本文也會定期刷新相關(guān)介紹。
默認(rèn)設(shè)備和平板對應(yīng)于小設(shè)備、中設(shè)備及大設(shè)備,本示例以這三類設(shè)備場景為例,介紹不同設(shè)備上的UX設(shè)計。天氣主頁在不同設(shè)備上的設(shè)計圖如下所示。
另外,大設(shè)備中天氣主頁還允許用戶開啟或者隱藏側(cè)邊欄。
從天氣應(yīng)用在各設(shè)備上的UX設(shè)計圖中,可以觀察到如下UX的一些“規(guī)律”:
- 在不同的屏幕寬度下,應(yīng)用的整體風(fēng)格基本保持一致。
- 在相近的屏幕寬度范圍內(nèi),應(yīng)用的布局基本不變;在不同的屏幕寬度范圍內(nèi),應(yīng)用的布局有較大差異。
- 應(yīng)用在小屏幕下顯示的元素,是大屏幕中顯示元素的子集。
- 考慮到屏幕尺寸及顯示效果,大屏幕中可以顯示的元素數(shù)量一定不少于小屏幕。
- 為充分利用屏幕尺寸優(yōu)勢,大屏幕可以有其獨有的元素或設(shè)計(如本示例中的側(cè)邊欄)。
如此,既在各設(shè)備上體現(xiàn)了UX的一致性,也在各設(shè)備上體現(xiàn)了UX的差異性,從而既可以保障各設(shè)備上應(yīng)用界面的體驗,也可以最大程度復(fù)用界面代碼。
在[應(yīng)用UX設(shè)計章節(jié)]中,將詳細(xì)介紹應(yīng)用的UX設(shè)計規(guī)則。
工程管理及調(diào)試
在本文IDE使用章節(jié)中,將詳細(xì)介紹一多的工程創(chuàng)建及管理等,本小節(jié)僅介紹最基礎(chǔ)的工程創(chuàng)建及多設(shè)備預(yù)覽調(diào)試。
工程創(chuàng)建
一多應(yīng)用的工程創(chuàng)建過程,與傳統(tǒng)應(yīng)用并無較大差異。只需在工程創(chuàng)建過程中,注意在“Device Type”選項中勾選所有該應(yīng)用期望運行的目標(biāo)設(shè)備類型,保證后續(xù)該應(yīng)用可以在所有目標(biāo)設(shè)備上正確安裝即可。
預(yù)覽調(diào)試
在代碼開發(fā)過程中,可以開啟預(yù)覽器,并打開“Multi-profile preview”開關(guān),實時觀察應(yīng)用在不同設(shè)備下的表現(xiàn)。
特別的,還可以點擊“+ New Profile”按鈕,新增自定義預(yù)覽器。
頁面開發(fā)
天氣應(yīng)用中涉及較多的頁面和彈窗,本小節(jié)以天氣主頁為例,簡單介紹不同設(shè)備下的頁面實現(xiàn)思路。
觀察天氣主頁在不同設(shè)備上的UX設(shè)計圖,可以進(jìn)行如下設(shè)計:
- 將天氣主頁劃分為9個基礎(chǔ)區(qū)域,如:
- 基礎(chǔ)區(qū)域9僅在大設(shè)備上顯示,基礎(chǔ)區(qū)域1-8雖然在各設(shè)備上始終展示但其尺寸及區(qū)域內(nèi)的布局基本保持不變,可以結(jié)合[自適應(yīng)布局]能力以[自定義組件]的形式分別實現(xiàn)這9個基礎(chǔ)區(qū)域。
- 基礎(chǔ)區(qū)域1-8之間的布局在不同設(shè)備上有較大差異,可以使用響應(yīng)式布局中的[柵格布局]能力實現(xiàn)組件間的布局效果。
- 展開和隱藏側(cè)邊欄的功能可以通過[側(cè)邊欄組件]來實現(xiàn)。側(cè)邊欄是大設(shè)備上獨有的,借助響應(yīng)式布局中的[媒體查詢]能力,控制僅在大設(shè)備上展示側(cè)邊欄即可。
主頁基礎(chǔ)區(qū)域
天氣主頁中的9個基礎(chǔ)區(qū)域介紹及實現(xiàn)方案如下表所示。
編號 | 簡介 | 實現(xiàn)方案 |
---|---|---|
1 | 標(biāo)題欄 | 自適應(yīng)布局拉伸能力。 |
2 | 天氣概覽 | Row和Column組件,并指定其子組件按照主軸起始方向?qū)R或居中對齊。 |
3 | 每小時天氣 | 自適應(yīng)布局延伸能力 。 |
4 | 每日天氣 | 自適應(yīng)布局延伸能力 。 |
5 | 空氣質(zhì)量 | Canvas畫布組件繪制空氣質(zhì)量圖,并使用Row組件和Column組件控制內(nèi)部元素的布局。 |
6 | 生活指數(shù) | 自適應(yīng)布局均分能力。 |
7 | 日出日落 | Canvas畫布組件繪制日出日落圖 。 |
8 | 應(yīng)用信息 | Row和Column組件,并指定其子組件居中對齊。 |
9 | 側(cè)邊導(dǎo)航欄 | 綜合運用自適應(yīng)布局中的拉伸能力、占比能力和延伸能力 。 |
天氣主頁涉及的內(nèi)容較多,因篇幅限制,本小節(jié)僅介紹區(qū)域3(每小時天氣)的實現(xiàn),讀者可以自行查看開源代碼,了解其它基礎(chǔ)區(qū)域的實現(xiàn)。
延伸能力是指容器組件內(nèi)的子組件,按照其在列表中的先后順序,隨容器組件尺寸變化顯示或隱藏。隨著可用顯示區(qū)域的增加,用戶可以看到的“每小時天氣”信息也不斷增加,故“每小時天氣”可以通過延伸能力實現(xiàn),其核心代碼如下所示。
import { Forecast, getHoursData, MyDataSource, Style } from '@ohos/common';
@Component
export default struct HoursWeather {
private hoursData: Forecast[] = getHoursData(0);
@State hoursDataResource: MyDataSource = new MyDataSource(this.hoursData);
build() {
// 通過列表組件實現(xiàn)延伸能力
List() {
LazyForEach(this.hoursDataResource, (hoursItem:IDataSource) = > {
ListItem() {
// 具體每個小時的天氣情況
Column() {
// ...
}
}
})
}
.height(Style.CARD_HEIGHT)
.borderRadius(Style.NORMAL_RADIUS)
.backgroundColor(Style.CARD_BACKGROUND_COLOR)
// 將列表方向設(shè)置為水平方向
.listDirection(Axis.Horizontal)
}
}
城市天氣詳情
天氣主頁右側(cè)的城市天氣詳情由區(qū)域1-8組成,區(qū)域1(標(biāo)題欄)始終固定在頁面頂部,區(qū)域2-8在不同設(shè)備下的布局不同且可以隨頁面上下滾動。本小節(jié)介紹如何實現(xiàn)城市天氣詳情中區(qū)域2~8的布局效果。
設(shè)備屏幕可能無法一次性顯示區(qū)域2-8的所有內(nèi)容,故需要在外層增加滾動組件(即Scroll組件)以支持上下滾動。不同設(shè)備下區(qū)域2-8的相對位置一共有三套不同的布局,可以借助響應(yīng)式布局中的[柵格布局]實現(xiàn)這一效果。本示例中將柵格在不同場景下分別劃分為4列、8列和12列,區(qū)域2-8在不同場景下的布局如下表所示。
說明: 為提升用戶體驗,大設(shè)備側(cè)邊欄隱藏狀態(tài)下,每日天氣與空氣質(zhì)量的相對順序發(fā)生了改變??梢哉{(diào)整通過GridCol柵格子組件的order屬性,實現(xiàn)目標(biāo)效果。
import AirQuality from './AirQuality'; //組件請參考相關(guān)實例
import HoursWeather from './HoursWeather';
import IndexHeader from './IndexHeader';
import IndexEnd from './IndexEnd';
import LifeIndex from './LifeIndex';
import MultidayWeather from './MultidayWeather';
import SunCanvas from './SunCanvas';
import { CityListData, Style } from '@ohos/common';
@Component
export default struct HomeContent {
private cityListData: CityListData | undefined = undefined;
private index: number = 1;
@Prop showSideBar: boolean;
@State headerOpacity: number = 1;
build() {
// 支持滾動
Scroll() {
GridRow({
columns: { sm: 4, md: 8, lg: this.showSideBar ? 8 : 12 },
gutter: { x: Style.GRID_GUTTER, y: Style.GRID_GUTTER },
breakpoints: { reference: BreakpointsReference.WindowSize } }) {
// 天氣概覽
GridCol({ span: { sm: 4, md: 8, lg: this.showSideBar ? 8 : 12 }, order: 1 }) {
IndexHeader({ headerDate: this.cityListData.header, index: this.index })
.opacity(this.headerOpacity)
}
// 每小時天氣
GridCol({ span: { sm: 4, md: 8, lg: 8 }, order: 2 }) {
HoursWeather({ hoursData: this.cityListData.hoursData })
}
// 每日天氣
GridCol({ span: 4, order: {sm: 3, md: 3, lg: this.showSideBar ? 3 : 4} }) {
MultidayWeather({ weekData: this.cityListData.weekData })
}
// 空氣質(zhì)量
GridCol({ span: 4, order: {sm: 4, md: 4, lg: this.showSideBar ? 4 : 3} }) {
AirQuality({ airData: this.cityListData.airData, airIndexData: this.cityListData.airIndex })
}
// 生活指數(shù)
GridCol({ span: 4, order: 5 }) {
LifeIndex({ lifeData: this.cityListData.suitDate })
}
// 日出日落
GridCol({ span: 4, order: 6 }) {
SunCanvas()
}
// 應(yīng)用信息
GridCol({ span: { sm: 4, md: 8, lg: this.showSideBar ? 8 : 12 }, order: 7 }) {
IndexEnd()
}
}
}
.width('100%')
}
}
主頁整體實現(xiàn)
綜合考慮各設(shè)備下的效果,天氣主頁的根節(jié)點使用側(cè)邊欄組件:
- 小設(shè)備和中設(shè)備既不展示側(cè)邊欄,也不提供控制側(cè)邊欄顯示和隱藏的按鈕。
- 大設(shè)備默認(rèn)展示側(cè)邊欄,同時提供控制側(cè)邊欄顯示和隱藏的按鈕。
另外主頁右側(cè)的城市天氣詳情,支持左右滑動切換城市,可以使用Swiper組件實現(xiàn)目標(biāo)效果。
- 小設(shè)備和中設(shè)備開啟Swiper組件的導(dǎo)航點,引導(dǎo)用戶通過左右滑動切換不同城市。
- 大設(shè)備中用戶通過點擊側(cè)邊欄中的城市列表即可高效的切換不同城市,此時需要關(guān)閉Swiper組件的導(dǎo)航點。
import HomeContent from './home/HomeContent'; //組件請參考相關(guān)實例
import IndexTitleBar from './home/IndexTitleBar';
import SideContent from './home/SideContent';
import { CityListData, getCityListWeatherData } from '@ohos/common';
@Entry
@Component
struct Home {
@State cityListWeatherData: CityListData[] = getCityListWeatherData();
@State curBp: string = 'md';
@State showSideBar: boolean = false;
![搜狗高速瀏覽器截圖20240326151344.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/62f255bd68ec41dd822ecfb742e3e1fb~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=645&h=308&s=29733&e=png&b=fffefe)
build() {
SideBarContainer(SideBarContainerType.Embed) {
// 左側(cè)側(cè)邊欄
SideContent({ showSideBar: $showSideBar })
// 右側(cè)內(nèi)容區(qū)
Flex({direction: FlexDirection.Column}) {
// 基礎(chǔ)區(qū)域1標(biāo)題欄
IndexTitleBar({ curBp: this.curBp, showSideBar: $showSideBar })
.height(56)
// 天氣詳情,通過Swiper組件實現(xiàn)左右滑動切換城市的效果
Swiper() {
ForEach(this.cityListWeatherData, (item:CityListData, index) = > {
HomeContent({ showSideBar: this.showSideBar, cityListData: item, index: index })
})
}
// 大設(shè)備關(guān)閉導(dǎo)航點
.indicator(this.curBp !== 'lg')
.width('100%')
}
}
.height('100%')
.sideBarWidth('33.3%')
// 通過狀態(tài)變量,控制不同設(shè)備下側(cè)邊欄的顯隱狀態(tài)
.showSideBar(this.showSideBar)
}
}
`HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
最終,天氣首頁的運行效果如下圖所示。
功能開發(fā)
應(yīng)用開發(fā)不僅包含應(yīng)用頁面開發(fā),還包括應(yīng)用后端功能開發(fā)以及服務(wù)器端開發(fā)等。服務(wù)器端開發(fā)不在本文的討論范圍內(nèi),本小節(jié)僅介紹多設(shè)備上應(yīng)用功能開發(fā)的注意事項。
如前文所示,本示例的目標(biāo)運行設(shè)備是小設(shè)備、中設(shè)備和大設(shè)備,對應(yīng)實際的設(shè)備類型為默認(rèn)設(shè)備和平板等。這些設(shè)備運行的都是標(biāo)準(zhǔn)系統(tǒng),其系統(tǒng)能力一致,所以無需做特別考慮。但是在超小設(shè)備(對應(yīng)的實際設(shè)備類型為智能穿戴設(shè)備等)上,考慮CPU、內(nèi)存、硬盤等硬件限制,往往會對系統(tǒng)進(jìn)行裁剪。如果在應(yīng)用后端功能開發(fā)時調(diào)用當(dāng)前系統(tǒng)沒有的能力,就可能會引發(fā)異常。
通常有兩種方式解決上述問題:
- 在應(yīng)用安裝包中描述其需要的系統(tǒng)能力,保證本應(yīng)用僅被分發(fā)和安裝到可以滿足其訴求的系統(tǒng)中。
- 在使用特定系統(tǒng)能力前,通過canIUse接口判斷系統(tǒng)能力是否存在,進(jìn)而執(zhí)行不同的邏輯。
審核編輯 黃宇
-
鴻蒙
+關(guān)注
關(guān)注
57文章
2339瀏覽量
42805 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3713瀏覽量
16254
發(fā)布評論請先 登錄
相關(guān)推薦
評論