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