1# 窗口管理开发常见问题 2 3 4## 如何获取状态栏和导航栏高度(API 9) 5 6**解决措施** 7 8在加载窗口内容之前,采用systemAvoidAreaChange事件监听。 9 10**代码示例** 11 12``` 13// MainAbility.ts 14import window from '@ohos.window'; 15 16/** 17 * 设置沉浸式窗口,并获取状态栏和导航栏高度 18 * @param mainWindow 主窗口对象 19 */ 20async function enterImmersion(mainWindow: window.Window) { 21 window.on("systemBarTintChange", (data) => { 22 let avoidAreaRect = data.regionTint[0].region; //data.regionTint是个数组,包含状态栏、导航栏的矩形区域坐标。 23 }) 24 await mainWindow.setFullScreen(true) 25 await mainWindow.setSystemBarEnable(["status", "navigation"]) 26 await mainWindow.systemBarProperties({ 27 navigationBarColor: "#00000000", 28 statusBarColor: "#00000000", 29 navigationBarContentColor: "#FF0000", 30 statusBarContentColor: "#FF0000" 31 }) 32} 33export default class MainAbility extends Ability { 34 // do something 35 async onWindowStageCreate(windowStage: window.WindowStage) { 36 let mainWindow = await windowStage.getMainWindow() 37 await enterImmersion(mainWindow) 38 windowStage.loadContent('pages/index') 39 } 40 // do something 41} 42``` 43 44 45## 应用如何设置隐藏顶部的状态栏(API 9) 46 47**解决措施** 48 49在UIAbility的onWindowStageCreate的生命周期中设置setWindowSystemBarEnable接口即可。 50 51**代码示例** 52 53``` 54onWindowStageCreate(windowStage){ 55 windowStage.getMainWindowSync().setWindowSystemBarEnable([]) 56 ...... 57} 58``` 59 60**参考链接** 61 62[窗口基础能力文档](../reference/apis-arkui/js-apis-window.md) 63 64## 如何锁定设备竖屏,使得窗口不随屏幕旋转(API 9) 65 66适用于Stage模型。 67 68**解决措施** 69 70采用窗口的setPreferredOrientation方法可以实现该效果,将orientation参数设置为window.Orientation.PORTRAIT时,可锁定屏幕为竖屏。 71 72**代码示例** 73 74``` 75import window from "@ohos.window"; 76//1.获取窗口实例对象,新建窗口使用createWindow方法,获取已有的窗口使用findWindow方法 77let windowClass = null; 78let config = {name: "alertWindow", windowType: window.WindowType.TYPE_SYSTEM_ALERT, ctx: this.context}; 79try { 80 let promise = window.createWindow(config); 81 promise.then((data)=> { 82 windowClass = data; 83 console.info('Succeeded in creating the window. Data:' + JSON.stringify(data)); 84 }).catch((err)=>{ 85 console.error('Failed to create the Window. Cause:' + JSON.stringify(err)); 86 });} catch (exception) { 87 console.error('Failed to create the window. Cause: ' + JSON.stringify(exception)); 88} 89//2.窗口实例使用setPreferredOrientation方法,设置窗口的显示方向,PORTRAIT为固定竖屏,其他方向可参照参考链接 90let orientation = window.Orientation.PORTRAIT; 91if (windowClass) { 92 windowClass.setPreferredOrientation(orientation, (err) => { 93 if (err.code) { 94 console.error('Failed to set window orientation. Cause: ' + JSON.stringify(err)); 95 return; 96 } 97 console.info('Succeeded in setting window orientation.'); 98} 99``` 100 101**参考链接** 102 103[window.Orientation](../reference/apis-arkui/js-apis-window.md#orientation9) 104 105## 调用Window实例的setWindowSystemBarProperties接口设置窗口状态栏和导航栏的高亮属性时不生效(API 9) 106 107适用于Stage模型。 108 109**解决措施** 110 111状态栏字体高亮属性的本质就只是让字体变成白色。调用window实例的setWindowSystemBarProperties接口时,如果设置了状态栏内容颜色statusBarContentColor,就以开发者设置的颜色为准,isStatusBarLightIcon状态栏字体高亮属性就不生效;同理,如果设置了导航栏内容颜色navigationBarContentColor,isNavigationBarLightIcon导航栏字体高亮属性就不生效。 112 113**参考链接** 114 115[window.SystemBarProperties](../reference/apis-arkui/js-apis-window.md#systembarproperties) 116 117 118## 如何保持屏幕常亮(API 9) 119 120**解决措施** 121 122设置屏幕常亮,不熄屏。 123 124获取窗口实例对象后,调用[setWindowKeepScreenOn方法](../reference/apis-arkui/js-apis-window.md#setwindowkeepscreenon9)可设置屏幕是否常亮。 125 126**代码示例** 127 128``` 129let isKeepScreenOn = true; 130try { 131 windowClass.setWindowKeepScreenOn(isKeepScreenOn, (err) => { 132 if (err.code) { 133 console.error('Failed to set the screen to be always on. Cause: ' + JSON.stringify(err)); 134 return; 135 } 136 console.info('Succeeded in setting the screen to be always on.'); 137 }); 138} catch (exception) { 139 console.error('Failed to set the screen to be always on. Cause: ' + JSON.stringify(exception)); 140} 141``` 142 143 144## 如何监听窗口大小的变化(API 9) 145 146获取窗口实例对象后,可以通过[window.on('windowSizeChange')](../reference/apis-arkui/js-apis-window.md#onwindowsizechange7)方法实现对窗口尺寸大小变化的监听。 147 148需要注意的是,在window侧如果窗口大小没发生变化,此监听不会被触发。如直接旋转180度的情况下,窗口大小并没有改变,此时不会通知回调。在这种情况下,应用可以通过监听[display.on('change')](../reference/apis-arkui/js-apis-display.md#displayonaddremovechange)事件,在callback中通过display接口来获取窗口尺寸大小。 149 150``` 151try { 152 windowClass.on('windowSizeChange', (data) => { 153 console.info('Succeeded in enabling the listener for window size changes. Data: ' + JSON.stringify(data)); 154 }); 155} catch (exception) { 156 console.error('Failed to enable the listener for window size changes. Cause: ' + JSON.stringify(exception)); 157} 158``` 159 160## 如何监听当前屏幕的横竖屏状态(API 10) 161 162**解决措施** 163 164应用可以通过display.on监听屏幕状态改变。 165 166**参考链接** 167 168[开启显示设备变化的监听](../reference/apis-arkui/js-apis-display.md#displayonaddremovechange) 169 170## 如何实现页面跟随屏幕横竖屏自动旋转(API 10) 171 172**解决措施** 173 1741.Abilty级别配置:在模块配置文件module.json5中将EntryAbility设置为"orientation"。 1752.动态设置:使用window.setPreferredOrientation设置窗口方向。 176 177**代码示例** 178```ts 179import window from '@ohos.window'; 180import display from '@ohos.display'; 181 182const TAG = 'foo' 183const ORIENTATION: Array<string> = ['垂直', '水平', '反向垂直', '反向水平'] 184 185@Entry 186@Component 187struct ScreenTest { 188 @State rotation: number = 0 189 @State message: string = ORIENTATION[this.rotation] 190 191 aboutToAppear() { 192 this.setOrientation() 193 194 let callback = async () => { 195 let d = await display.getDefaultDisplaySync() 196 this.rotation = d.rotation 197 this.message = ORIENTATION[this.rotation] 198 console.info(TAG, JSON.stringify(d)) 199 } 200 try { 201 display.on("change", callback); // 监听屏幕状态改变 202 } catch (exception) { 203 console.error(TAG, 'Failed to register callback. Code: ' + JSON.stringify(exception)); 204 } 205 } 206 207 setOrientation() { 208 try { 209 window.getLastWindow(getContext(this), (err, data) => { // 获取window实例 210 if (err.code) { 211 console.error(TAG, 'Failed to obtain the top window. Cause: ' + JSON.stringify(err)); 212 return; 213 } 214 let windowClass = data; 215 console.info(TAG, 'Succeeded in obtaining the top window. Data: ' + JSON.stringify(data)); 216 217 let orientation = window.Orientation.AUTO_ROTATION; // 设置窗口方向为传感器自动旋转模式。 218 try { 219 windowClass.setPreferredOrientation(orientation, (err) => { 220 if (err.code) { 221 console.error(TAG, 'Failed to set window orientation. Cause: ' + JSON.stringify(err)); 222 return; 223 } 224 console.info(TAG, 'Succeeded in setting window orientation.'); 225 }); 226 } catch (exception) { 227 console.error(TAG, 'Failed to set window orientation. Cause: ' + JSON.stringify(exception)); 228 } 229 ; 230 }); 231 } catch (exception) { 232 console.error(TAG, 'Failed to obtain the top window. Cause: ' + JSON.stringify(exception)); 233 } 234 ; 235 } 236 237 build() { 238 Row() { 239 Column() { 240 Text(`${this.rotation}`).fontSize(25) 241 Text(`${this.message}`).fontSize(25) 242 } 243 .width("100%") 244 } 245 .height("100%") 246 } 247} 248``` 249**参考链接** 250 251[设置窗口的显示方向属性](../reference/apis-arkui/js-apis-window.md#setpreferredorientation9) 252[开启显示设备变化的监听](../reference/apis-arkui/js-apis-display.md#displayonaddremovechange) 253 254## 在display.on('change')监听回调中,无法使用Window实例获取更新后的窗口大小(API 10) 255 256**解决措施** 257 258旋转涉及[@ohos.window](../reference/apis-arkui/js-apis-window.md)和[@ohos.display](../reference/apis-arkui/js-apis-display.md)两个模块,处于不同进程。由于旋转完后display的更新时间早于window的更新时间(display旋转时直接宽高互换,提前可预知;window要等ArkUI布局完成才能确定窗口大小,耗时长),故在display触发变化时获取窗口信息会存在时序问题(窗口信息还未更新完成,此时使用Window实例获取到的还是原来的宽高)。应用可以通过display.on('change')接口监听显示设备变化,在callback中通过Display实例获取屏幕的width、height、orientation等信息。 259 260**错误示例** 261 262```ts 263// display先更新 264display.on('change', async (data) => { 265 let newDisplay: display.Display = display.getDefaultDisplaySync(); 266 console.info('Orientation: ' + newDisplay.orientation); 267 let windowClass: window.Window = await window.getLastWindow(this.context); 268 // window后更新,获取到的还是原来的宽高 269 let windowProperties = windowClass.getWindowProperties(); 270 console.info('Width: ' + windowProperties.windowRect.width + 271 ', height: ' + windowProperties.windowRect.height); 272 // 请确保已获取到相关Window实例,即windowClass 273 windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_CUTOUT); 274}); 275``` 276 277**正确示例** 278 279```ts 280display.on('change', (data) => { 281 console.info('Succeeded in enabling the listener for display changes. Data: ' + 282 JSON.stringify(data)); 283 let newDisplay: display.Display = display.getDefaultDisplaySync(); 284 console.info('Orientation: ' + newDisplay.orientation + 'width: ' + 285 newDisplay.width + ', height: ' + newDisplay.height); 286}); 287``` 288 289**参考链接** 290 291[display.on('change')](../reference/apis-arkui/js-apis-display.md#displayonaddremovechange) 292 293## 如何同时获取屏幕方向orientation和系统规避区avoidAreaChange信息(API 10) 294 295可以通过[on('avoidAreaChange')](../reference/apis-arkui/js-apis-window.md#onavoidareachange9)接口监听窗口系统规避区域的变化,在callback中获取avoidAreaChange信息,并通过Display实例获取屏幕方向orientation等信息。 296 297```ts 298// 请确保已获取到相关Window实例,即windowClass 299windowClass.on('avoidAreaChange', async (data) => { 300 console.info('Succeeded in enabling the listener for avoid area changes. Type: ' + 301 JSON.stringify(data.type) + ', area ' + JSON.stringify(data.area)); 302 let newDisplay: display.Display = display.getDefaultDisplaySync(); 303 console.info('Orientation: ' + newDisplay.orientation); 304 let windowClass: window.Window = await window.getLastWindow(this.context); 305 windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_CUTOUT); 306}); 307``` 308 309<!--no_check-->