1# 设置浮层(OverlayManager) 2 3**浮层(OverlayManager)** 用于将自定义的UI内容展示在页面(Page)之上,在Dialog、Popup、Menu、BindSheet、BindContentCover和Toast等组件之下,展示的范围为当前窗口安全区内。可适用于常驻悬浮等场景。 4 5 6 7可以通过使用[UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md#uicontext)中的[getOverlayManager](../reference/apis-arkui/js-apis-arkui-UIContext.md#getoverlaymanager12)方法获取当前UI上下文关联的[OverlayManager](../reference/apis-arkui/js-apis-arkui-UIContext.md#overlaymanager12)对象,再通过该对象调用对应方法。 8 9## 规格约束 10 11* OverlayManager上节点的层级在Page页面层级之上,在Dialog、Popup、Menu、BindSheet、BindContentCover和Toast等组件之下。 12* OverlayManager添加的节点显示和消失时没有默认动画。 13* OverlayManager上节点安全区域内外的绘制方式与Page一致,键盘避让方式与Page一致。 14* 与OverlayManager相关的属性推荐采用AppStorage来进行应用全局存储,以免切换页面后属性值发生变化从而导致业务错误。 15 16## 设置浮层 17 18在OverlayManager上[新增指定节点(addComponentContent)](../reference/apis-arkui/js-apis-arkui-UIContext.md#addcomponentcontent12)、[删除指定节点(removeComponentContent)](../reference/apis-arkui/js-apis-arkui-UIContext.md#removecomponentcontent12)、[显示所有节点(showAllComponentContents)](../reference/apis-arkui/js-apis-arkui-UIContext.md#showallcomponentcontents12)和[隐藏所有节点(hideAllComponentContents)](../reference/apis-arkui/js-apis-arkui-UIContext.md#hideallcomponentcontents12)。 19 20```ts 21import { ComponentContent, OverlayManager } from '@kit.ArkUI'; 22 23class Params { 24 text: string = ""; 25 offset: Position; 26 27 constructor(text: string, offset: Position) { 28 this.text = text; 29 this.offset = offset; 30 } 31} 32 33@Builder 34function builderText(params: Params) { 35 Column() { 36 Text(params.text) 37 .fontSize(30) 38 .fontWeight(FontWeight.Bold) 39 }.offset(params.offset) 40} 41 42@Entry 43@Component 44struct OverlayExample { 45 @State message: string = 'ComponentContent'; 46 private uiContext: UIContext = this.getUIContext(); 47 private overlayNode: OverlayManager = this.uiContext.getOverlayManager(); 48 @StorageLink('contentArray') contentArray: ComponentContent<Params>[] = []; 49 @StorageLink('componentContentIndex') componentContentIndex: number = 0; 50 @StorageLink('arrayIndex') arrayIndex: number = 0; 51 @StorageLink("componentOffset") componentOffset: Position = { x: 0, y: 80 }; 52 53 build() { 54 Column({ space: 10 }) { 55 Button("递增componentContentIndex: " + this.componentContentIndex).onClick(() => { 56 ++this.componentContentIndex; 57 }) 58 Button("递减componentContentIndex: " + this.componentContentIndex).onClick(() => { 59 --this.componentContentIndex; 60 }) 61 Button("增加ComponentContent" + this.contentArray.length).onClick(() => { 62 let componentContent = new ComponentContent( 63 this.uiContext, wrapBuilder<[Params]>(builderText), 64 new Params(this.message + (this.contentArray.length), this.componentOffset) 65 ); 66 this.contentArray.push(componentContent); 67 this.overlayNode.addComponentContent(componentContent, this.componentContentIndex); 68 }) 69 Button("递增arrayIndex: " + this.arrayIndex).onClick(() => { 70 ++this.arrayIndex; 71 }) 72 Button("递减arrayIndex: " + this.arrayIndex).onClick(() => { 73 --this.arrayIndex; 74 }) 75 Button("删除ComponentContent" + this.arrayIndex).onClick(() => { 76 if (this.arrayIndex >= 0 && this.arrayIndex < this.contentArray.length) { 77 let componentContent = this.contentArray.splice(this.arrayIndex, 1); 78 this.overlayNode.removeComponentContent(componentContent.pop()); 79 } else { 80 console.info("arrayIndex有误"); 81 } 82 }) 83 Button("显示ComponentContent" + this.arrayIndex).onClick(() => { 84 if (this.arrayIndex >= 0 && this.arrayIndex < this.contentArray.length) { 85 let componentContent = this.contentArray[this.arrayIndex]; 86 this.overlayNode.showComponentContent(componentContent); 87 } else { 88 console.info("arrayIndex有误"); 89 } 90 }) 91 Button("隐藏ComponentContent" + this.arrayIndex).onClick(() => { 92 if (this.arrayIndex >= 0 && this.arrayIndex < this.contentArray.length) { 93 let componentContent = this.contentArray[this.arrayIndex]; 94 this.overlayNode.hideComponentContent(componentContent); 95 } else { 96 console.info("arrayIndex有误"); 97 } 98 }) 99 Button("显示所有ComponentContent").onClick(() => { 100 this.overlayNode.showAllComponentContents(); 101 }) 102 Button("隐藏所有ComponentContent").onClick(() => { 103 this.overlayNode.hideAllComponentContents(); 104 }) 105 106 Button("跳转页面").onClick(() => { 107 this.getUIContext().getRouter().pushUrl({ 108 url: 'pages/Second' 109 }) 110 }) 111 } 112 .width('100%') 113 .height('100%') 114 } 115} 116``` 117 118 119显示一个始终在屏幕左侧的悬浮球,点击可以弹出alertDialog弹窗。 120 121```ts 122import { ComponentContent, OverlayManager } from '@kit.ArkUI'; 123 124class Params { 125 context: UIContext; 126 offset: Position; 127 constructor(context: UIContext, offset: Position) { 128 this.context = context; 129 this.offset = offset; 130 } 131} 132@Builder 133function builderOverlay(params: Params) { 134 Column() { 135 Stack(){ 136 }.width(50).height(50).backgroundColor(Color.Yellow).position(params.offset).borderRadius(50) 137 .onClick(() => { 138 params.context.showAlertDialog( 139 { 140 title: 'title', 141 message: 'Text', 142 autoCancel: true, 143 alignment: DialogAlignment.Center, 144 gridCount: 3, 145 confirm: { 146 value: 'Button', 147 action: () => {} 148 }, 149 cancel: () => {} 150 } 151 ) 152 }) 153 }.focusable(false).width('100%').height('100%').hitTestBehavior(HitTestMode.Transparent) 154} 155 156@Entry 157@Component 158struct OverlayExample { 159 @State message: string = 'ComponentContent'; 160 private uiContext: UIContext = this.getUIContext(); 161 private overlayNode: OverlayManager = this.uiContext.getOverlayManager(); 162 private overlayContent:ComponentContent<Params>[] = []; 163 controller: TextInputController = new TextInputController(); 164 165 aboutToAppear(): void { 166 let uiContext = this.getUIContext(); 167 let componentContent = new ComponentContent( 168 this.uiContext, wrapBuilder<[Params]>(builderOverlay), 169 new Params(uiContext, {x:0, y: 100}) 170 ); 171 this.overlayNode.addComponentContent(componentContent, 0); 172 this.overlayContent.push(componentContent); 173 } 174 175 aboutToDisappear(): void { 176 let componentContent = this.overlayContent.pop(); 177 this.overlayNode.removeComponentContent(componentContent); 178 } 179 180 build() { 181 Column() { 182 183 } 184 .width('100%') 185 .height('100%') 186 } 187} 188 189``` 190 191 192从API version 18开始,可以通过调用UIContext中getOverlayManager方法获取OverlayManager对象,并利用该对象在指定层级上新增指定节点([addComponentContentWithOrder](../reference/apis-arkui/js-apis-arkui-UIContext.md#addcomponentcontentwithorder18)),层次高的浮层会覆盖在层级低的浮层之上。 193 194```ts 195import { ComponentContent, LevelOrder, OverlayManager } from '@kit.ArkUI'; 196 197class Params { 198 text: string = ""; 199 offset: Position; 200 constructor(text: string, offset: Position) { 201 this.text = text; 202 this.offset = offset; 203 } 204} 205 206@Builder 207function builderTopText(params: Params) { 208 Column() { 209 Stack(){ 210 Text(params.text) 211 .fontSize(30) 212 .fontWeight(FontWeight.Bold) 213 }.width(300).height(200).padding(5).backgroundColor('#F7F7F7').alignContent(Alignment.Top) 214 }.offset(params.offset) 215} 216 217@Builder 218function builderNormalText(params: Params) { 219 Column() { 220 Stack(){ 221 Text(params.text) 222 .fontSize(30) 223 .fontWeight(FontWeight.Bold) 224 }.width(300).height(400).padding(5).backgroundColor('#D5D5D5').alignContent(Alignment.Top) 225 }.offset(params.offset) 226} 227 228@Entry 229@Component 230struct Index { 231 private ctx: UIContext = this.getUIContext(); 232 private overlayManager: OverlayManager = this.ctx.getOverlayManager(); 233 @StorageLink('contentArray') contentArray: ComponentContent<Params>[] = []; 234 @StorageLink('componentContentIndex') componentContentIndex: number = 0; 235 @StorageLink('arrayIndex') arrayIndex: number = 0; 236 @StorageLink('componentOffset') componentOffset: Position = {x: 0, y: 80}; 237 238 build() { 239 Row() { 240 Column({ space: 5 }) { 241 Button('点击打开置顶弹窗') 242 .onClick(() => { 243 let componentContent = new ComponentContent( 244 this.ctx, wrapBuilder<[Params]>(builderTopText), 245 new Params('我是置顶弹窗', this.componentOffset) 246 ); 247 this.contentArray.push(componentContent); 248 this.overlayManager.addComponentContentWithOrder(componentContent, LevelOrder.clamp(100000)); 249 }) 250 Button('点击打开普通弹窗') 251 .onClick(() => { 252 let componentContent = new ComponentContent( 253 this.ctx, wrapBuilder<[Params]>(builderNormalText), 254 new Params('我是普通弹窗', this.componentOffset) 255 ); 256 this.contentArray.push(componentContent); 257 this.overlayManager.addComponentContentWithOrder(componentContent, LevelOrder.clamp(0)); 258 }) 259 Button("点击移除弹窗").onClick(()=>{ 260 if (this.arrayIndex >= 0 && this.arrayIndex < this.contentArray.length) { 261 let componentContent = this.contentArray.splice(this.arrayIndex, 1); 262 this.overlayManager.removeComponentContent(componentContent.pop()); 263 } else { 264 console.info("arrayIndex有误"); 265 } 266 }) 267 }.width('100%') 268 } 269 } 270} 271``` 272 273