一、setWindowLayoutFullScreen(true)
- 设置主窗口或子窗口的布局是否为沉浸式布局,使用Promise异步回调。
- 沉浸式布局生效时,布局不避让状态栏与导航栏,组件可能产生与其重叠的情况。
- 非沉浸式布局生效时,布局避让状态栏与导航栏,组件不会与其重叠。
-
窗口的布局是否为沉浸式布局(该沉浸式布局状态栏、导航栏仍然显示)。true表示沉浸式布局;false表示非沉浸式布局。
1、EntryAbility直接设置
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
GlobalContext.get().setContext(this.context);
windowStage.getMainWindow().then((windowObj: window.Window) => {
//设置沉浸式
windowObj.setWindowLayoutFullScreen(true).catch((error: BusinessError) => {
hilog.error(0x0001, 'testTag', `Failed to setWindowLayoutFullScreen. Code: ${error.code}`);
})
//获取并保存状态栏高度
let avoidArea = windowObj.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
GlobalContext.get().setObject('state_bar_height', avoidArea.topRect.height);
windowStage.loadContent('pages/Index', (err) => {
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.');
});
})
}
}
未做状态栏高度处理页面代码
@Entry
@Component
struct ImmersivePage {
build() {
Column() {
Text('setWindowLayoutFullScreen(true) 沉浸式')
.fontSize(50)
.fontColor(Color.Red)
}
.height('100%')
.width('100%')
}
}
状态栏高度处理页面代码
@Entry
@Component
struct ImmersivePage {
build() {
Column() {
//添加状态高度,可以封装好一个通用
Text()
.backgroundColor(Color.Orange)
.height(px2vp(GlobalContext.get().getT<number>('state_bar_height')))
.width('100%')
Text('setWindowLayoutFullScreen(true) 沉浸式')
.fontSize(50)
.fontColor(Color.Red)
}
.height('100%')
.width('100%')
}
}
2、在对应页面设置setWindowLayoutFullScreen(true)沉浸式
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
GlobalContext.get().setContext(this.context);
windowStage.getMainWindow().then((windowObj: window.Window) => {
//获取并保存状态栏高度
let avoidArea = windowObj.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
GlobalContext.get().setObject('state_bar_height', avoidArea.topRect.height);
//保存窗口全局使用
GlobalContext.get().window = windowStage.getMainWindowSync()
windowStage.loadContent('pages/Index', (err) => {
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.');
});
})
}
}
@Entry
@Component
struct ImmersivePage {
build() {
Column() {
Text('当前页面设置setWindowLayoutFullScreen(true) 沉浸式')
.fontSize(50)
.fontColor(Color.Red)
}
.height('100%')
.width('100%')
}
aboutToAppear(): void {
//设置沉浸式
GlobalContext.get().window?.setWindowLayoutFullScreen(true)
}
aboutToDisappear(): void {
//沉浸式恢复
GlobalContext.get().window?.setWindowLayoutFullScreen(false)
}
}
3、使用方式总结
- 直接设置setWindowLayoutFullScreen(true),会导致全部页面内容到状态栏,需要手动添加状态栏高度,可以考虑封装好一个。
- 在页面显示前(aboutToAppear)获取窗口(windowStage.getMainWindowSync())设置setWindowLayoutFullScreen(true)实现沉浸式,页面销毁(aboutToDisappear)设置setWindowLayoutFullScreen(false)回归正常。
但是这样做有个不好影响就是上一个页面会有向下动的视觉,体验不是很好。
二、expandSafeArea()
- 控制组件扩展其安全区域。
1、未设置expandSafeArea
@Entry
@Component
struct ImmersivePage {
build() {
Column() {
Text('未设置 expandSafeArea 沉浸式')
.fontSize(50)
.fontColor(Color.Red)
}
.backgroundColor(Color.Orange)
.height('100%')
.width('100%')
}
}
2、设置expandSafeArea背景色沉浸
对父容器设置才是背景色沉浸,如果对Text设置会连带文字一起沉浸到状态栏。
@Entry
@Component
struct ImmersivePage {
build() {
Column() {
Text('设置 expandSafeArea 沉浸式')
.fontSize(50)
.fontColor(Color.Red)
}
.expandSafeArea()//设置沉浸式
.backgroundColor(Color.Orange)
.height('100%')
.width('100%')
}
}
3、设置expandSafeArea图片沉浸
@Entry
@Component
struct ImmersivePage {
build() {
Stack() {
Image($rawfile('img.png'))
.expandSafeArea()//设置沉浸式
Text('设置 expandSafeArea 沉浸式')
.fontSize(50)
.fontColor(Color.White)
}
.height('100%')
.width('100%')
}
}
未设置沉浸式 | 设置沉浸式 |
---|---|
4、多层组件也能设置expandSafeArea沉浸,只要父组件没有限制其到状态栏
@Entry
@Component
struct ImmersivePage {
build() {
Stack({ alignContent: Alignment.TopStart }) {
this.LayoutBuilder()
Text('设置 expandSafeArea 沉浸式')
.fontSize(50)
.fontColor(Color.White)
}
.height('100%')
.width('100%')
}
@Builder
LayoutBuilder() {
Column() {
Image($rawfile('img.png'))
.expandSafeArea() //设置沉浸式
}
}
}
5、多个组件也能设置expandSafeArea沉浸
@Entry
@Component
struct ImmersivePage {
build() {
Stack({ alignContent: Alignment.TopStart }) {
this.LayoutBuilder()
Text('设置 expandSafeArea 沉浸式')
.fontSize(50)
.fontColor(Color.White)
.expandSafeArea() //设置沉浸式1
}
.height('100%')
.width('100%')
}
@Builder
LayoutBuilder() {
Column() {
Image($rawfile('img.png'))
.expandSafeArea() //设置沉浸式2
}
}
}
6、使用方式总结
- expandSafeArea设置沉浸式更灵活,可以根据情况对其中一个或多个组件设置沉浸式
- expandSafeArea设置沉浸式不会导致页面上下抖动
7、说明
设置expandSafeArea属性进行组件绘制扩展时,组件不能设置固定宽高尺寸(百分比除外)。
安全区域不会限制内部组件的布局和大小,不会裁剪内部组件。
当父容器是滚动容器时,设置expandSafeArea属性不生效。
设置expandSafeArea()时,不传参,走默认值处理;设置expandSafeArea([],[])时,相当于入参是空数组,此时设置expandSafeArea属性不生效。
组件设置expandSafeArea之后生效的条件为:
1.type为SafeAreaType.KEYBOARD时默认生效,组件不避让键盘。
2.设置其他type,组件的边界与安全区域重合时组件能够延伸到安全区域下。例如:设备顶部状态栏高度100,那么组件在屏幕中的绝对位置需要为0 <= y <= 100。
组件延伸到安全区域下,在安全区域处的事件,如点击事件等可能会被系统拦截,优先给状态栏等系统组件响应。
滚动类容器内的组件不建议设置expandSafeArea属性,如果设置,需要按照组件嵌套关系,将当前节点到滚动类祖先容器间所有直接节点设置expandSafeArea属性,否则expandSafeArea属性在滚动后可能会失效
三、Navigation()+NavDestination()
Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(NavDestination的子组件),首页和非首页通过路由进行切换。
作为子页面的根容器,用于显示Navigation的内容区。
该组件从API Version 11开始默认支持安全区避让特性(默认值为:expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])),开发者可以重写该属性覆盖默认行为,API Version 11之前的版本需配合expandSafeArea属性实现安全区避让。
@Builder
export function ImmersivePageBuilder() {
ImmersivePage()
}
@Component
export struct ImmersivePage {
pathStack: NavPathStack = new NavPathStack()
build() {
NavDestination() {
Stack({ alignContent: Alignment.TopStart }) {
Text('设置 NavDestination 沉浸式')
.fontSize(50)
.fontColor(Color.White)
}
.height('100%')
.width('100%')
}
.hideTitleBar(true) //设置沉浸式
.backgroundColor(Color.Orange) //设置沉浸式
.backgroundImage($rawfile('img.png'))//图片设置沉浸式,容易图片拉伸
.backgroundImageSize({ width: '100%', height: '100%' })//图片设置沉浸式,容易图片拉伸
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
})
}
}
背景色沉浸式 | 图片沉浸式 |
---|---|
使用方式总结
- 默认还是使用expandSafeArea实现沉浸式。
- 推荐在这使用颜色沉浸式,用图片容易造成拉伸,确定用图片可以单独对图片使用expandSafeArea沉浸式。