• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&lt;void&gt;,
33  secondary: Callback&lt;void&gt;,
34  extra?: Callback&lt;void&gt;,
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| ![](figures/foldsplitcontainer-1.png) | ![](figures/foldsplitcontainer-2.png) | ![](figures/foldsplitcontainer-3.png) |
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| ![](figures/foldsplitcontainer-4.png) | ![](figures/foldsplitcontainer-5.png) | ![](figures/foldsplitcontainer-6.png) |
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| ![](figures/foldsplitcontainer-7.png) | ![](figures/foldsplitcontainer-8.png) | ![](figures/foldsplitcontainer-11.png) |
682|                                       | ![](figures/foldsplitcontainer-9.png) | ![](figures/foldsplitcontainer-12.png) |
683|                                       | ![](figures/foldsplitcontainer-10.png) | ![](figures/foldsplitcontainer-13.png) |
684