常見問題
如何查詢?cè)O(shè)備類型
設(shè)備類型分為default(默認(rèn)設(shè)備)、tablet、tv、wearable、2in1等,有多種查詢?cè)O(shè)備類型的方式。
- 通過命令行的方式查詢?cè)O(shè)備類型。 通過命令行查詢指定系統(tǒng)參數(shù)(const.product.devicetype)進(jìn)而確定設(shè)備類型。
# 方法一 hdc shell param get "const.product.devicetype" # 方法二 hdc shell cat /etc/param/ohos.para | grep const.product.devicetype
- 在應(yīng)用開發(fā)過程中查詢?cè)O(shè)備類型。
- 通過deviceInfo查詢?cè)O(shè)備類型。
import deviceInfo from'@ohos.deviceInfo' @Entry @Component struct GetDeviceTypeSample { @State deviceType:string='unknown' aboutToAppear() { this.deviceType= deviceInfo.deviceType } build() { Column() { Text(this.deviceType).fontSize(24) } .width('100%') .height('100%') } }
- 通過deviceInfo查詢?cè)O(shè)備類型。
如何在不同設(shè)備上為Ability配置不同的啟動(dòng)模式
應(yīng)用由一個(gè)或多個(gè)Ability組成,Ability支持單實(shí)例、多實(shí)例和指定實(shí)例3種[啟動(dòng)模式],啟動(dòng)模式可以在[配置文件(module.json5)]中通過launchType字段配置。啟動(dòng)模式對(duì)應(yīng)Ability被啟動(dòng)時(shí)的行為,對(duì)啟動(dòng)模式的詳細(xì)說明如下:
啟動(dòng)模式 | 描述 | 說明 開發(fā)前請(qǐng)熟悉鴻蒙開發(fā)指導(dǎo)文檔 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md ]點(diǎn)擊或者復(fù)制轉(zhuǎn)到。 |
---|---|---|
multiton | 多實(shí)例 | 每次startAbility都會(huì)啟動(dòng)一個(gè)新的實(shí)例。 |
singleton | 單實(shí)例 | 系統(tǒng)中最多只可以存在一個(gè)實(shí)例,startAbility時(shí),如果系統(tǒng)中已存在相應(yīng)的Ability實(shí)例,則復(fù)用該實(shí)例。 |
specified | 指定實(shí)例 | 運(yùn)行時(shí)由Ability內(nèi)部業(yè)務(wù)決定是否創(chuàng)建多實(shí)例。 |
默認(rèn)設(shè)備屏幕尺寸較小,采用multiton啟動(dòng)模式不僅無法給用戶提供便利,反而可能消耗更多系統(tǒng)資源,故通常采用singleton啟動(dòng)模式。平板屏幕尺寸較大且可能支持自由窗口,對(duì)于文檔編輯、網(wǎng)頁瀏覽等場景,使用multiton啟動(dòng)模式可以提升用戶體驗(yàn)。
本文中將默認(rèn)設(shè)備和平板等歸為同一泛類,推薦同一泛類的設(shè)備共用HAP,同時(shí)本文也介紹了如何通過自適應(yīng)布局能力和響應(yīng)式布局能力開發(fā)出適配不同設(shè)備的頁面。這里將補(bǔ)充介紹,如何實(shí)現(xiàn)Ability在不同設(shè)備上以不同的模式啟動(dòng)。
launchType字段配置為specified時(shí),系統(tǒng)會(huì)根據(jù)AbilityStage的onAcceptWant的返回值確定是否創(chuàng)建新的實(shí)例。對(duì)于同一個(gè)應(yīng)用,如果key已經(jīng)存在,則復(fù)用該key對(duì)應(yīng)的Ability,如果key不存在則新創(chuàng)建Ability。
可以將配置文件中的launchType字段配置為specified,同時(shí)在應(yīng)用中加入如下代碼以實(shí)現(xiàn)目標(biāo)效果。
- 非平板設(shè)備,直接將設(shè)備類型作為key,保證每次啟動(dòng)的key相同,即以單實(shí)例模式運(yùn)行。
- 平板設(shè)備,將設(shè)備類型與毫秒級(jí)時(shí)間戳疊加作為key,保證每次啟動(dòng)的key不同,即以多實(shí)例模式運(yùn)行。
// MyAbilityStage.ts
import AbilityStage from "@ohos.app.ability.AbilityStage"
import deviceInfo from'@ohos.deviceInfo'
import Want from '@ohos.app.ability.Want'
export default class MyAbilityStage extends AbilityStage {
...
private generateKey(): string {
// 如果是平板,則將設(shè)備類型和毫秒級(jí)時(shí)間戳疊加作為key,保證每次啟動(dòng)的key都不同
if (deviceInfo.deviceType === 'tablet') {
return deviceInfo.deviceType + (new Date()).valueOf()
}
// 如果不是平板,直接以設(shè)備類型作為key,每次啟動(dòng)的key相同
return deviceInfo.deviceType
}
onAcceptWant(want: Want) : string{
return this.generateKey()
}
}
如何開啟自由窗口
自由窗口功能默認(rèn)是關(guān)閉的,可以通過如下方式開啟自由窗口功能。
# 取出窗口配置文件,并將文件中的< decor enable="false" >< /decor >修改為< decor enable="true" >< /decor >
hdc file recv system/etc/window/resources/window_manager_config.xml ./
# 以可讀寫的模式重新掛載根目錄,并更新配置文件
hdc shell mount -o rw,remount /
hdc file send window_manager_config.xml system/etc/window/resources/window_manager_config.xml
# 重啟設(shè)備,配置生效
hdc shell reboot
屏幕較小,通過手指操作窗口較為不便時(shí),建議外接鼠標(biāo)進(jìn)行操作。
- 鼠標(biāo)在應(yīng)用頂部懸停,即可召喚出窗口工具欄。
- 點(diǎn)擊窗口工具欄中的縮放按鈕(從左到右第二個(gè)),即可讓應(yīng)用以自由窗口的模式顯示。
- 在自由窗口模式下,可以通過拖動(dòng)應(yīng)用窗口的邊框或頂角,改變窗口尺寸同時(shí)觸發(fā)應(yīng)用顯示刷新。 在調(diào)整窗口尺寸的過程中,窗口尺寸可能超出屏幕尺寸。此時(shí)應(yīng)用顯示正常,但受限于屏幕尺寸,在屏幕中只能看到應(yīng)用部分區(qū)域的顯示??梢酝ㄟ^移動(dòng)窗口位置,查看應(yīng)用其它區(qū)域的顯示。
如何限制自由窗口的尺寸調(diào)節(jié)范圍
自適應(yīng)布局可以保證窗口尺寸在一定范圍內(nèi)變化時(shí),頁面的顯示是正常的。當(dāng)窗口尺寸變化較大時(shí),就需要額外借助響應(yīng)式布局能力(如斷點(diǎn)等)調(diào)整頁面結(jié)構(gòu)以保證顯示正常。通常每個(gè)斷點(diǎn)都需要開發(fā)者精心適配以獲得最佳的顯示效果,考慮到設(shè)計(jì)及開發(fā)成本等實(shí)際因素的限制,應(yīng)用不可能適配從零到正無窮的所有窗口寬度。
不同設(shè)備或不同設(shè)備狀態(tài),系統(tǒng)默認(rèn)的自由窗口尺寸的調(diào)節(jié)范圍可能不同。開發(fā)者可以在[應(yīng)用配置文件]中限制應(yīng)用中各個(gè)Ability的自由窗口尺寸調(diào)節(jié)范圍,配置文件中影響自由窗口尺寸調(diào)節(jié)范圍的字段如下表所示。
配置文件字段 | 數(shù)據(jù)類型 | 描述 |
---|---|---|
minWindowWidth | 數(shù)值 | 標(biāo)識(shí)該ability支持的最小的窗口寬度, 寬度單位為vp。 |
minWindowHeight | 數(shù)值 | 標(biāo)識(shí)該ability支持的最小的窗口高度, 高度單位為vp。 |
maxWindowWidth | 數(shù)值 | 標(biāo)識(shí)該ability支持的最大的窗口寬度,寬度單位為vp。 |
maxWindowHeight | 數(shù)值 | 標(biāo)識(shí)該ability支持的最大的窗口高度, 高度單位為vp。 |
minWindowRatio | 數(shù)值 | 標(biāo)識(shí)該ability支持的最小的寬高比。 |
maxWindowRatio | 數(shù)值 | 標(biāo)識(shí)該ability支持的最大的寬高比。 |
如下所示,通過配置文件分別限制自由窗口的最大和最小尺寸。
{
"module": {
...
"abilities": [
{
...
"minWindowWidth": 320,
"minWindowHeight": 240,
"maxWindowWidth": 1440,
"maxWindowHeight": 900,
"minWindowRatio": 0.5,
"maxWindowRatio": 2,
}
]
}
}
如何獲取組件的尺寸
實(shí)際開發(fā)過程中,開發(fā)者可能有獲取頁面中某個(gè)組件或某塊區(qū)域的尺寸的訴求,以便通過手動(dòng)計(jì)算等進(jìn)行更精確的布局計(jì)算及優(yōu)化。
開發(fā)者可以通過[組件區(qū)域變化事件](即組件顯示的尺寸、位置等發(fā)生變化時(shí)觸發(fā)的事件)來獲取指定組件的尺寸。
如下所示,通過onAreaChange事件獲取Row組件(頁面中白色區(qū)域)的尺寸。
@Entry
@Component
struct OnAreaChangeSample {
@State rate: number = 0.8
@State info: string = ''
// 底部滑塊,可以通過拖拽滑塊改變?nèi)萜鞒叽?/span>
@Builder slider() {
Slider({ value: this.rate * 100, min: 30, max: 80, style: SliderStyle.OutSet })
.blockColor(Color.White)
.width('60%')
.onChange((value: number) = > {
this.rate = value / 100;
})
.position({ x: '20%', y: '80%' })
}
build() {
Column() {
Column() {
Row() {
Text(this.info).fontSize(20).lineHeight(22)
}
.borderRadius(12)
.padding(24)
.backgroundColor('#FFFFFF')
.width(this.rate * 100 + '%')
.onAreaChange((oldValue: Area, newValue: Area) = > {
this.info = JSON.stringify(newValue)
})
}
this.slider()
}
.width('100%')
.height('100%')
.backgroundColor('#F1F3F5')
.justifyContent(FlexAlign.Center)
}
}
如何解決頂部單張大圖問題
解決方案
頂部背景圖被拉伸時(shí),可以通過設(shè)置背景圖片的[backgroundImageSize]屬性,使得圖片大小能夠合理顯示,達(dá)到適配效果。
布局效果
參考代碼
@Entry
@Component
struct ImageClip {
build() {
// 設(shè)置背景圖片的backgroundImageSize屬性,使得圖片大小能夠合理顯示
Column()
.width('100%')
.height(300)
.backgroundColor('#ccc')
.backgroundImage($r('app.media.ImageOne'))
.backgroundImageSize(ImageSize.Cover)
.backgroundImagePosition(Alignment.Center)
}
}
如何解決Item內(nèi)容過大
解決方案
在大屏上,Listitem內(nèi)容會(huì)過大,頁面整體瀏覽內(nèi)容減少。可通過以下兩種方法解決:
- 設(shè)置List列的最小寬度和最大寬度,使List組件根據(jù)寬度自適應(yīng)決定列數(shù)。
- 借助柵格行組件[GridRow],調(diào)整不同的斷點(diǎn)下List組件的寬度。
布局效果
參考代碼
@Entry
@Component
struct ListLayout {
@State data: Resource[] = new Array(5).fill($r("app.media.image"))
@State breakPoint: string = 'sm'
build() {
GridRow() {
GridCol({ span: { sm: 12, md: 12, lg: 12 } }) {
List({ space: 24 }) {
ForEach(this.data, (item: Resource) = > {
ListItem() {
Image(item).margin({ left: 12, right: 12 })
}
})
}
// 設(shè)置列最小寬度和最大寬度
.lanes({ minLength: 300, maxLength: 360 }).padding(12)
}
}.onBreakpointChange((breakpoint: string) = > {
this.breakPoint = breakpoint
})
}
}
List() {
// ...
}
// 根據(jù)斷點(diǎn)設(shè)置List列數(shù)
.lanes(this.breakPoint === 'sm' ? 1 : 2)
如何解決Banner圖片過大
解決方案
在大屏上,Swiper圖片顯示內(nèi)容過大,可以通過增加Swiper展示圖片數(shù)來調(diào)整圖片顯示大小。外層可以使用柵格組件[GridRow],通過調(diào)用OnBreakpointChange事件,調(diào)整不同的斷點(diǎn)下Swiper的前后邊距,實(shí)現(xiàn)在不同屏幕尺寸上的顯示不同Swiper圖片數(shù)。
布局效果
參考代碼
@Entry
@Component
struct SwiperLayout {
@State data: Resource[] = new Array(5).fill($r("app.media.sky"))
@State breakPoint: string = 'sm'
build() {
Row() {
GridRow() {
GridCol({ span: { sm: 12, md: 12, lg: 12 } }) {
Swiper() {
ForEach(this.data, (item: Resource) = > {
Image(item).width('100%').height(180)
})
}
.width('100%')
.itemSpace(24)
// 根據(jù)斷點(diǎn)設(shè)置Swiper前后邊距
.prevMargin(this.breakPoint === 'sm' ? 0 : 100)
.nextMargin(this.breakPoint === 'sm' ? 0 : 100)
}
}.onBreakpointChange((breakpoint: string) = > {
this.breakPoint = breakpoint
})
.height("60%")
.borderWidth(2)
}
}
}
如何解決信息流圖片過大
解決方案
針對(duì)信息流單張圖片過大的情況,設(shè)置[aspectRatio]和[constrainSize]屬性,可以通過對(duì)圖片的布局和尺寸進(jìn)行約束,達(dá)到適配效果。
布局效果
參考代碼
@Entry
@Component
struct ImageConstrainSize {
@State breakPoint: string = 'sm'
build() {
GridRow(){
GridCol({ span: { sm: 12, md: 12, lg: 12 } }){
Column(){
Text('一次開發(fā),多端部署,讓開發(fā)者可以基于一種設(shè)計(jì),高效構(gòu)建多端可運(yùn)行的應(yīng)用。一次開發(fā),多端部署,讓開發(fā)者可以基于一種設(shè)計(jì),高效構(gòu)建多端可運(yùn)行的應(yīng)用。')
// 設(shè)置aspectRatio和constrainSize屬性,可以對(duì)圖片的布局和尺寸進(jìn)行約束
Image($r('app.media.ImageTwo'))
.width('30%')
.aspectRatio(0.5)
.constraintSize({ maxWidth: 240, minWidth: 180 })
Text('一次開發(fā),多端部署,讓開發(fā)者可以基于一種設(shè)計(jì),高效構(gòu)建多端可運(yùn)行的應(yīng)用。一次開發(fā),多端部署,讓開發(fā)者可以基于一種設(shè)計(jì),高效構(gòu)建多端可運(yùn)行的應(yīng)用。')
}.alignItems(HorizontalAlign.Start)
}
}.onBreakpointChange((breakpoint: string) = > {
this.breakPoint = breakpoint
})
}
}
如何解決信息流_4宮格圖片過大
解決方案
在大屏上,Grid組件里的4宮格圖片大小過大,頁面瀏覽區(qū)域變少??梢越柚鷸鸥裥薪M件[GridRow]來調(diào)整不同的斷點(diǎn)下Grid的寬度,解決大屏上Grid組件4宮格圖片過大的問題。
布局效果
參考代碼
@Entry
@Component
struct GridLayout {
@State data: Resource[] = new Array(4).fill($r("app.media.image"))
@State breakPoint: string = 'sm'
build() {
GridRow() {
GridCol({ span: { sm: 12, md: 12, lg: 12 } }) {
Column() {
Text('一次開發(fā),多端部署,讓開發(fā)者可以基于一種設(shè)計(jì),高效構(gòu)建多端可運(yùn)行的應(yīng)用。')
Grid() {
ForEach(this.data, (item: Resource) = > {
GridItem() {
Image(item).width('100%').aspectRatio(1)
}
})
}.columnsTemplate('1fr 1fr')
.columnsGap(24)
.rowsGap(24)
// 根據(jù)斷點(diǎn)設(shè)置Grid寬度
.width(this.breakPoint === 'md' ? '60%' : '100%')
}.width('100%').alignItems(HorizontalAlign.Start)
}
}.onBreakpointChange((breakpoint: string) = > {
this.breakPoint = breakpoint
})
}
}
如何解決信息流_9宮格圖片過大
解決方案
在大屏上,Grid組件里的9宮格圖片大小過大,頁面整體瀏覽內(nèi)容減少,可以設(shè)置Grid組件寬度和寬高比,使Grid組件保持固定大小,不會(huì)隨著屏幕尺寸變化而變化。
布局效果
參考代碼
`HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
@Entry
@Component
struct GridWidth {
@State data: Resource[] = new Array(9).fill($r("app.media.sky"))
build() {
Column() {
Text('一次開發(fā),多端部署,讓開發(fā)者可以基于一種設(shè)計(jì),高效構(gòu)建多端可運(yùn)行的應(yīng)用。')
Grid() {
ForEach(this.data, (item: Resource) = > {
GridItem() {
Image(item).width('100%').aspectRatio(1)
}
})
}
.columnsTemplate('1fr 1fr 1fr')
.columnsGap(12)
.rowsGap(12)
// 設(shè)置固定寬度和寬高比
.width(360)
.aspectRatio(1)
.padding(12)
}
.alignItems(HorizontalAlign.Start)
}
}
審核編輯 黃宇
-
鴻蒙
+關(guān)注
關(guān)注
57文章
2302瀏覽量
42689 -
鴻蒙OS
+關(guān)注
關(guān)注
0文章
188瀏覽量
4359
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論