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