1# FoldSplitContainer 2 3 4**FoldSplitContainer** is a layout container designed to manage regions for two-panel and three-panel arrangements on a foldable device across various states, including the expanded state, the hover state, and the folded state. 5 6 7> **NOTE** 8> 9> This component is supported since API version 12. Updates will be marked with a superscript to indicate their earliest API version. 10 11## Modules to Import 12 13```ts 14import { FoldSplitContainer } from '@kit.ArkUI'; 15``` 16 17## Child Components 18 19Not supported 20 21## FoldSplitContainer 22 23FoldSplitContainer({ 24 primary: Callback<void>, 25 secondary: Callback<void>, 26 extra?: Callback<void>, 27 expandedLayoutOptions: ExpandedRegionLayoutOptions, 28 hoverModeLayoutOptions: HoverModeRegionLayoutOptions, 29 foldedLayoutOptions: FoldedRegionLayoutOptions, 30 animationOptions?: AnimateParam, 31 onHoverStatusChange?: OnHoverStatusChangeHandler 32}) 33 34Creates a **FoldSplitContainer** component to manage regions for two-panel and three-panel arrangements on a foldable device across various states, including the expanded state, the hover state, and the folded state. 35 36**Decorator**: \@Component 37 38**Atomic service API**: This API can be used in atomic services since API version 12. 39 40**System capability**: SystemCapability.ArkUI.ArkUI.Full 41 42| Name| Type| Mandatory| Decorator| Description| 43| -------- | -------- | -------- | -------- | -------- | 44| primary | ()=>void | Yes| @BuilderParam | Callback function for the primary region.| 45| secondary | ()=>void | Yes| @BuilderParam | Callback function for the secondary region.| 46| extra | ()=>void | No| @BuilderParam | Callback function for the extra region. If this parameter is not provided, there is no corresponding region.| 47| expandedLayoutOptions | [ExpandedRegionLayoutOptions](#expandedregionlayoutoptions) | Yes| @Prop | Layout information for the expanded state.| 48| hoverModeLayoutOptions | [HoverModeRegionLayoutOptions](#hovermoderegionlayoutoptions) | Yes| @Prop | Layout information for the hover state.| 49| foldedLayoutOptions | [FoldedRegionLayoutOptions](#foldedregionlayoutoptions) | Yes| @Prop | Layout information for the folded state.| 50| animationOptions | [AnimateParam](ts-explicit-animation.md#animateparam) \| null | No| @Prop | Animation settings. The value **null** indicates that the animation is disabled.| 51| onHoverStatusChange | [OnHoverStatusChangeHandler](#onhoverstatuschangehandler) | No| - | Callback function triggered when the foldable device enters or exits the hover state.| 52 53## ExpandedRegionLayoutOptions 54 55Defines the layout information for the expanded state. 56 57**Atomic service API**: This API can be used in atomic services since API version 12. 58 59**System capability**: SystemCapability.ArkUI.ArkUI.Full 60 61| Name| Type| Mandatory| Description| 62| -------- | -------- | -------- | -------- | 63| isExtraRegionPerpendicular | boolean | No| Whether the extra region extends perpendicularly through the entire component from top to bottom. This setting takes effect only when **extra** is effective. Default value: **true**| 64| verticalSplitRatio | number | No| Height ratio between the primary and secondary regions. Default value: **PresetSplitRatio.LAYOUT_1V1**| 65| horizontalSplitRatio | number | No| Width ratio between the primary and extra regions. This setting takes effect only when **extra** is effective. Default value: **PresetSplitRatio.LAYOUT_3V2**| 66| extraRegionPosition | [ExtraRegionPosition](#extraregionposition) | No| Position information of the extra region. This setting takes effect only when **isExtraRegionPerpendicular** is **false**. Default value: **ExtraRegionPosition.top**| 67 68## HoverModeRegionLayoutOptions 69 70Defines the layout information for the hover state. 71 72**Atomic service API**: This API can be used in atomic services since API version 12. 73 74**System capability**: SystemCapability.ArkUI.ArkUI.Full 75 76| Name| Type| Mandatory| Description| 77| -------- | -------- | -------- | -------- | 78| showExtraRegion | boolean | No| Whether to display the extra region in the half-folded state. Default value: **false**| 79| horizontalSplitRatio | number | No| Width ratio between the primary and extra regions. This setting takes effect only when **extra** is effective. Default value: **PresetSplitRatio.LAYOUT_3V2**| 80| extraRegionPosition | [ExtraRegionPosition](#extraregionposition) | No| Position information of the extra region. This setting takes effect only when **showExtraRegion** is set. Default value: **ExtraRegionPosition.top**| 81 82> **NOTE** 83> 84> 1. When the device is in the hover state, there is an avoid area, and layout calculations need to account for the impact of the avoid area on the layout. 85> 2 In the hover state, the upper half screen is used for display, and the lower half is used for interaction. 86 87## FoldedRegionLayoutOptions 88 89Defines the layout information for the folded state. 90 91**Atomic service API**: This API can be used in atomic services since API version 12. 92 93**System capability**: SystemCapability.ArkUI.ArkUI.Full 94 95| Name| Type| Mandatory| Description| 96| -------- | -------- | -------- | -------- | 97| verticalSplitRatio | number | No| Height ratio between the primary and secondary regions. Default value: **PresetSplitRatio.LAYOUT_1V1**| 98 99## OnHoverStatusChangeHandler 100 101type OnHoverStatusChangeHandler = (status: HoverModeStatus) => void 102 103Implements a handler for the **onHoverStatusChange** event. 104 105**Atomic service API**: This API can be used in atomic services since API version 12. 106 107**System capability**: SystemCapability.ArkUI.ArkUI.Full 108 109**Parameters** 110 111| Name| Type| Mandatory| Description| 112| -------- | -------- | -------- | -------- | 113| status | [HoverModeStatus](#hovermodestatus) | Yes| Callback function triggered when the foldable device enters or exits the hover state.| 114 115## HoverModeStatus 116 117Provides information about the device or application's folding, rotation, and window state. 118 119**Atomic service API**: This API can be used in atomic services since API version 12. 120 121**System capability**: SystemCapability.ArkUI.ArkUI.Full 122 123| Name| Type| Mandatory| Description| 124| -------- | -------- | -------- | -------- | 125| foldStatus | [display.FoldStatus](../js-apis-display.md#foldstatus10) | Yes| Fold status of the device.| 126| isHoverMode | boolean | Yes| Whether the application is in the hover state.| 127| appRotation | number | Yes| Rotation angle of the application.| 128| windowStatusType | [window.WindowStatusType](../js-apis-window.md#windowstatustype11) | Yes| Window mode.| 129 130## ExtraRegionPosition 131 132Provides the position information of the extra region. 133 134**Atomic service API**: This API can be used in atomic services since API version 12. 135 136**System capability**: SystemCapability.ArkUI.ArkUI.Full 137 138| Name| Value| Description| 139| -------- | -------- | -------- | 140| TOP | 1 | The extra region is in the upper half of the component.| 141| BOTTOM | 2 | The extra region is in the lower half of the component.| 142 143## PresetSplitRatio 144 145Enumerates the split ratios. 146 147**Atomic service API**: This API can be used in atomic services since API version 12. 148 149**System capability**: SystemCapability.ArkUI.ArkUI.Full 150 151| Name| Value| Description| 152| -------- | -------- | -------- | 153| LAYOUT_1V1 | 1 | 1:1.| 154| LAYOUT_3V2 | 1.5 | 3:2.| 155| LAYOUT_2V3 | 0.6666666666666666 | 2:3.| 156 157## Example 158 159### Example 1: Setting Up a Two-Panel Layout 160 161This example demonstrates how to control the region for a two-panel layout on a foldable screen across different states: folded, expanded, and hover. 162 163```ts 164import { FoldSplitContainer } from '@kit.ArkUI'; 165 166@Entry 167@Component 168struct TwoColumns { 169 @Builder 170 privateRegion() { 171 Text("Primary") 172 .backgroundColor('rgba(255, 0, 0, 0.1)') 173 .fontSize(28) 174 .textAlign(TextAlign.Center) 175 .height('100%') 176 .width('100%') 177 } 178 179 @Builder 180 secondaryRegion() { 181 Text("Secondary") 182 .backgroundColor('rgba(0, 255, 0, 0.1)') 183 .fontSize(28) 184 .textAlign(TextAlign.Center) 185 .height('100%') 186 .width('100%') 187 } 188 189 build() { 190 RelativeContainer() { 191 FoldSplitContainer({ 192 primary: () => { 193 this.privateRegion() 194 }, 195 secondary: () => { 196 this.secondaryRegion() 197 } 198 }) 199 } 200 .height('100%') 201 .width('100%') 202 } 203} 204``` 205 206| Folded| Expanded| Hover| 207| ----- | ------ | ------ | 208|  |  |  | 209 210### Example 2: Setting Up a Three-Panel Layout 211 212This example demonstrates how to control the region for a three-panel layout on a foldable screen across different states: folded, expanded, and hover. 213 214```ts 215import { FoldSplitContainer } from '@kit.ArkUI'; 216 217@Entry 218@Component 219struct ThreeColumns { 220 @Builder 221 privateRegion() { 222 Text("Primary") 223 .backgroundColor('rgba(255, 0, 0, 0.1)') 224 .fontSize(28) 225 .textAlign(TextAlign.Center) 226 .height('100%') 227 .width('100%') 228 } 229 230 @Builder 231 secondaryRegion() { 232 Text("Secondary") 233 .backgroundColor('rgba(0, 255, 0, 0.1)') 234 .fontSize(28) 235 .textAlign(TextAlign.Center) 236 .height('100%') 237 .width('100%') 238 } 239 240 @Builder 241 extraRegion() { 242 Text("Extra") 243 .backgroundColor('rgba(0, 0, 255, 0.1)') 244 .fontSize(28) 245 .textAlign(TextAlign.Center) 246 .height('100%') 247 .width('100%') 248 } 249 250 build() { 251 RelativeContainer() { 252 FoldSplitContainer({ 253 primary: () => { 254 this.privateRegion() 255 }, 256 secondary: () => { 257 this.secondaryRegion() 258 }, 259 extra: () => { 260 this.extraRegion() 261 } 262 }) 263 } 264 .height('100%') 265 .width('100%') 266 } 267} 268``` 269 270| Folded| Expanded| Hover| 271| ----- | ------ | ------ | 272|  |  |  | 273 274### Example 3: Setting Layout Information in Expanded State 275 276This example illustrates how to configure **ExpandedRegionLayoutOptions** to set the layout information for a foldable screen when it is in the expanded state. 277 278```ts 279import { 280 FoldSplitContainer, 281 PresetSplitRatio, 282 ExtraRegionPosition, 283 ExpandedRegionLayoutOptions, 284 HoverModeRegionLayoutOptions, 285 FoldedRegionLayoutOptions 286} from '@kit.ArkUI'; 287 288@Component 289struct Region { 290 @Prop title: string; 291 @BuilderParam content: () => void; 292 @Prop compBackgroundColor: string; 293 294 build() { 295 Column({ space: 8 }) { 296 Text(this.title) 297 .fontSize("24fp") 298 .fontWeight(600) 299 300 Scroll() { 301 this.content() 302 } 303 .layoutWeight(1) 304 .width("100%") 305 } 306 .backgroundColor(this.compBackgroundColor) 307 .width("100%") 308 .height("100%") 309 .padding(12) 310 } 311} 312 313const noop = () => { 314}; 315 316@Component 317struct SwitchOption { 318 @Prop label: string = "" 319 @Prop value: boolean = false 320 public onChange: (checked: boolean) => void = noop; 321 322 build() { 323 Row() { 324 Text(this.label) 325 Blank() 326 Toggle({ type: ToggleType.Switch, isOn: this.value }) 327 .onChange((isOn) => { 328 this.onChange(isOn); 329 }) 330 } 331 .backgroundColor(Color.White) 332 .borderRadius(8) 333 .padding(8) 334 .width("100%") 335 } 336} 337 338interface RadioOptions { 339 label: string; 340 value: Object | undefined | null; 341 onChecked: () => void; 342} 343 344@Component 345struct RadioOption { 346 @Prop label: string; 347 @Prop value: Object | undefined | null; 348 @Prop options: Array<RadioOptions>; 349 350 build() { 351 Row() { 352 Text(this.label) 353 Blank() 354 Column({ space: 4 }) { 355 ForEach(this.options, (option: RadioOptions) => { 356 Row() { 357 Radio({ 358 group: this.label, 359 value: JSON.stringify(option.value), 360 }) 361 .checked(this.value === option.value) 362 .onChange((checked) => { 363 if (checked) { 364 option.onChecked(); 365 } 366 }) 367 Text(option.label) 368 } 369 }) 370 } 371 .alignItems(HorizontalAlign.Start) 372 } 373 .alignItems(VerticalAlign.Top) 374 .backgroundColor(Color.White) 375 .borderRadius(8) 376 .padding(8) 377 .width("100%") 378 } 379} 380 381@Entry 382@Component 383struct Index { 384 @State expandedRegionLayoutOptions: ExpandedRegionLayoutOptions = { 385 horizontalSplitRatio: PresetSplitRatio.LAYOUT_3V2, 386 verticalSplitRatio: PresetSplitRatio.LAYOUT_1V1, 387 isExtraRegionPerpendicular: true, 388 extraRegionPosition: ExtraRegionPosition.TOP 389 }; 390 @State foldingRegionLayoutOptions: HoverModeRegionLayoutOptions = { 391 horizontalSplitRatio: PresetSplitRatio.LAYOUT_3V2, 392 showExtraRegion: false, 393 extraRegionPosition: ExtraRegionPosition.TOP 394 }; 395 @State foldedRegionLayoutOptions: FoldedRegionLayoutOptions = { 396 verticalSplitRatio: PresetSplitRatio.LAYOUT_1V1 397 }; 398 399 @Builder 400 MajorRegion() { 401 Region({ 402 title: "Folded state settings", 403 compBackgroundColor: "rgba(255, 0, 0, 0.1)", 404 }) { 405 Column({ space: 4 }) { 406 RadioOption({ 407 label: "Height ratio", 408 value: this.foldedRegionLayoutOptions.verticalSplitRatio, 409 options: [ 410 { 411 label: "1:1", 412 value: PresetSplitRatio.LAYOUT_1V1, 413 onChecked: () => { 414 this.foldedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_1V1 415 } 416 }, 417 { 418 label: "2:3", 419 value: PresetSplitRatio.LAYOUT_2V3, 420 onChecked: () => { 421 this.foldedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_2V3 422 } 423 }, 424 { 425 label: "3:2", 426 value: PresetSplitRatio.LAYOUT_3V2, 427 onChecked: () => { 428 this.foldedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_3V2 429 } 430 }, 431 { 432 label: "Not set", 433 value: undefined, 434 onChecked: () => { 435 this.foldedRegionLayoutOptions.verticalSplitRatio = undefined 436 } 437 } 438 ] 439 }) 440 } 441 .constraintSize({ minHeight: "100%" }) 442 } 443 } 444 445 @Builder 446 MinorRegion() { 447 Region({ 448 title: "Hover state settings", 449 compBackgroundColor: "rgba(0, 255, 0, 0.1)" 450 }) { 451 Column({ space: 4 }) { 452 RadioOption({ 453 label: "Width ratio", 454 value: this.foldingRegionLayoutOptions.horizontalSplitRatio, 455 options: [ 456 { 457 label: "1:1", 458 value: PresetSplitRatio.LAYOUT_1V1, 459 onChecked: () => { 460 this.foldingRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_1V1 461 } 462 }, 463 { 464 label: "2:3", 465 value: PresetSplitRatio.LAYOUT_2V3, 466 onChecked: () => { 467 this.foldingRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_2V3 468 } 469 }, 470 { 471 label: "3:2", 472 value: PresetSplitRatio.LAYOUT_3V2, 473 onChecked: () => { 474 this.foldingRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_3V2 475 } 476 }, 477 { 478 label: "Not set", 479 value: undefined, 480 onChecked: () => { 481 this.foldingRegionLayoutOptions.horizontalSplitRatio = undefined 482 } 483 }, 484 ] 485 }) 486 487 SwitchOption({ 488 label: "Show extra region", 489 value: this.foldingRegionLayoutOptions.showExtraRegion, 490 onChange: (checked) => { 491 this.foldingRegionLayoutOptions.showExtraRegion = checked; 492 } 493 }) 494 495 if (this.foldingRegionLayoutOptions.showExtraRegion) { 496 RadioOption({ 497 label: "Extra region location," 498 value: this.foldingRegionLayoutOptions.extraRegionPosition, 499 options: [ 500 { 501 label: "Top," 502 value: ExtraRegionPosition.TOP, 503 onChecked: () => { 504 this.foldingRegionLayoutOptions.extraRegionPosition = ExtraRegionPosition.TOP 505 } 506 }, 507 { 508 label: "Bottom," 509 value: ExtraRegionPosition.BOTTOM, 510 onChecked: () => { 511 this.foldingRegionLayoutOptions.extraRegionPosition = ExtraRegionPosition.BOTTOM 512 } 513 }, 514 { 515 label: "Not set", 516 value: undefined, 517 onChecked: () => { 518 this.foldingRegionLayoutOptions.extraRegionPosition = undefined 519 } 520 }, 521 ] 522 }) 523 } 524 } 525 .constraintSize({ minHeight: "100%" }) 526 } 527 } 528 529 @Builder 530 ExtraRegion() { 531 Region({ 532 title: "Expanded state settings," 533 compBackgroundColor: "rgba(0, 0, 255, 0.1)" 534 }) { 535 Column({ space: 4 }) { 536 RadioOption({ 537 label: "Width ratio," 538 value: this.expandedRegionLayoutOptions.horizontalSplitRatio, 539 options: [ 540 { 541 label: "1:1", 542 value: PresetSplitRatio.LAYOUT_1V1, 543 onChecked: () => { 544 this.expandedRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_1V1 545 } 546 }, 547 { 548 label: "2:3", 549 value: PresetSplitRatio.LAYOUT_2V3, 550 onChecked: () => { 551 this.expandedRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_2V3 552 } 553 }, 554 { 555 label: "3:2", 556 value: PresetSplitRatio.LAYOUT_3V2, 557 onChecked: () => { 558 this.expandedRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_3V2 559 } 560 }, 561 { 562 label: "Not set", 563 value: undefined, 564 onChecked: () => { 565 this.expandedRegionLayoutOptions.horizontalSplitRatio = undefined 566 } 567 }, 568 ] 569 }) 570 571 RadioOption({ 572 label: "Height ratio", 573 value: this.expandedRegionLayoutOptions.verticalSplitRatio, 574 options: [ 575 { 576 label: "1:1", 577 value: PresetSplitRatio.LAYOUT_1V1, 578 onChecked: () => { 579 this.expandedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_1V1 580 } 581 }, 582 { 583 label: "2:3", 584 value: PresetSplitRatio.LAYOUT_2V3, 585 onChecked: () => { 586 this.expandedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_2V3 587 } 588 }, 589 { 590 label: "3:2", 591 value: PresetSplitRatio.LAYOUT_3V2, 592 onChecked: () => { 593 this.expandedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_3V2 594 } 595 }, 596 { 597 label: "Not set", 598 value: undefined, 599 onChecked: () => { 600 this.expandedRegionLayoutOptions.verticalSplitRatio = undefined 601 } 602 } 603 ] 604 }) 605 606 SwitchOption({ 607 label: "Show extra region perpendicularly," 608 value: this.expandedRegionLayoutOptions.isExtraRegionPerpendicular, 609 onChange: (checked) => { 610 this.expandedRegionLayoutOptions.isExtraRegionPerpendicular = checked; 611 } 612 }) 613 614 if (!this.expandedRegionLayoutOptions.isExtraRegionPerpendicular) { 615 RadioOption({ 616 label: "Extra region location," 617 value: this.expandedRegionLayoutOptions.extraRegionPosition, 618 options: [ 619 { 620 label: "Top," 621 value: ExtraRegionPosition.TOP, 622 onChecked: () => { 623 this.expandedRegionLayoutOptions.extraRegionPosition = ExtraRegionPosition.TOP 624 } 625 }, 626 { 627 label: "Bottom," 628 value: ExtraRegionPosition.BOTTOM, 629 onChecked: () => { 630 this.expandedRegionLayoutOptions.extraRegionPosition = ExtraRegionPosition.BOTTOM 631 } 632 }, 633 { 634 label: "Not set", 635 value: undefined, 636 onChecked: () => { 637 this.expandedRegionLayoutOptions.extraRegionPosition = undefined 638 } 639 }, 640 ] 641 }) 642 } 643 } 644 .constraintSize({ minHeight: "100%" }) 645 } 646 } 647 648 build() { 649 Column() { 650 FoldSplitContainer({ 651 primary: () => { 652 this.MajorRegion() 653 }, 654 secondary: () => { 655 this.MinorRegion() 656 }, 657 extra: () => { 658 this.ExtraRegion() 659 }, 660 expandedLayoutOptions: this.expandedRegionLayoutOptions, 661 hoverModeLayoutOptions: this.foldingRegionLayoutOptions, 662 foldedLayoutOptions: this.foldedRegionLayoutOptions, 663 }) 664 } 665 .width("100%") 666 .height("100%") 667 } 668} 669``` 670 671| Folded| Expanded| Hover| 672| ----- | ------ | ------ | 673|  |  |  | 674| |  |  | 675| |  |  | 676