• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# FoldSplitContainer
2
3
4FoldSplitContainer分栏布局,实现折叠屏二分栏、三分栏在展开态、悬停态以及折叠态的区域控制。
5
6
7> **说明:**
8>
9> 该组件从API version 12开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
10>
11> 该组件不支持在Wearable设备上使用。
12
13## 导入模块
14
15```ts
16import { FoldSplitContainer } from '@kit.ArkUI';
17```
18
19## 子组件
20
2122
23## FoldSplitContainer
24
25FoldSplitContainer({
26  primary: Callback<void>,
27  secondary: Callback<void>,
28  extra?: Callback<void>,
29  expandedLayoutOptions: ExpandedRegionLayoutOptions,
30  hoverModeLayoutOptions: HoverModeRegionLayoutOptions,
31  foldedLayoutOptions: FoldedRegionLayoutOptions,
32  animationOptions?: AnimateParam,
33  onHoverStatusChange?: OnHoverStatusChangeHandler
34})
35
36实现折叠屏二分栏、三分栏在展开态、悬停态以及折叠态的区域控制的分栏布局。
37
38**装饰器类型:**\@Component
39
40**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
41
42**系统能力:** SystemCapability.ArkUI.ArkUI.Full
43
44| 名称 | 类型 | 必填 | 装饰器类型 | 说明 |
45| -------- | -------- | -------- | -------- | -------- |
46| primary | ()=>void | 是 | @BuilderParam | 主要区域回调函数。 |
47| secondary | ()=>void | 是 | @BuilderParam | 次要区域回调函数。 |
48| extra | ()=>void | 否 | @BuilderParam | 扩展区域回调函数,不传入的情况,没有对应区域。 |
49| expandedLayoutOptions | [ExpandedRegionLayoutOptions](#expandedregionlayoutoptions) | 是 | @Prop | 展开态布局信息。 |
50| hoverModeLayoutOptions | [HoverModeRegionLayoutOptions](#hovermoderegionlayoutoptions) | 是 | @Prop | 悬停态布局信息。 |
51| foldedLayoutOptions | [FoldedRegionLayoutOptions](#foldedregionlayoutoptions) | 是 | @Prop | 折叠态布局信息。 |
52| animationOptions | [AnimateParam](ts-explicit-animation.md#animateparam对象说明) \| null | 否 | @Prop | 设置动画效果相关的参数,null表示关闭动效。 |
53| onHoverStatusChange | [OnHoverStatusChangeHandler](#onhoverstatuschangehandler) | 否 | - | 折叠屏进入或退出悬停模式时触发的回调函数。 |
54
55## ExpandedRegionLayoutOptions
56
57展开态布局信息。
58
59**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
60
61**系统能力:** SystemCapability.ArkUI.ArkUI.Full
62
63| 名称 | 类型 | 必填 | 说明 |
64| -------- | -------- | -------- | -------- |
65| isExtraRegionPerpendicular | boolean | 否 | 扩展区域是否从上到下贯穿整个组件,当且仅当extra有效时此字段才生效。默认值:true。 |
66| verticalSplitRatio | number | 否 | 主要区域与次要区域之间的高度比例。默认值:PresetSplitRatio.LAYOUT_1V1。 |
67| horizontalSplitRatio | number | 否 | 主要区域与扩展区域之间的宽度比例,当且仅当extra有效时此字段才生效。默认值:PresetSplitRatio.LAYOUT_3V2。 |
68| extraRegionPosition | [ExtraRegionPosition](#extraregionposition) | 否 | 扩展区域的位置信息,当且仅当isExtraRegionPerpendicular = false有效时此字段才生效。默认值:ExtraRegionPosition.top。 |
69
70## HoverModeRegionLayoutOptions
71
72悬停态布局信息。
73
74**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
75
76**系统能力:** SystemCapability.ArkUI.ArkUI.Full
77
78| 名称 | 类型 | 必填 | 说明 |
79| -------- | -------- | -------- | -------- |
80| showExtraRegion | boolean | 否 | 可折叠屏幕在半折叠状态下是否显示扩展区域。默认值:false。 |
81| horizontalSplitRatio | number | 否 | 主要区域与扩展区域之间的宽度比例,当且仅当extra有效时此字段才生效。默认值:PresetSplitRatio.LAYOUT_3V2。 |
82| extraRegionPosition | [ExtraRegionPosition](#extraregionposition) | 否 | 扩展区域的位置信息,当且仅当showExtraRegion时此字段才生效。默认值:ExtraRegionPosition.top。 |
83
84> **说明:**
85>
86> 1.设备处于悬停态时,存在避让区域,布局计算需要考虑避让区域对布局的影响。
87> 2.在悬停模式下,屏幕上半部分用于显示,下半部分用于操作。
88
89## FoldedRegionLayoutOptions
90
91折叠态布局信息。
92
93**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
94
95**系统能力:** SystemCapability.ArkUI.ArkUI.Full
96
97| 名称 | 类型 | 必填 | 说明 |
98| -------- | -------- | -------- | -------- |
99| verticalSplitRatio | number | 否 | 主要区域与次要区域之间的高度比例。默认值:PresetSplitRatio.LAYOUT_1V1。 |
100
101## OnHoverStatusChangeHandler
102
103type OnHoverStatusChangeHandler = (status: HoverModeStatus) => void
104
105onHoverStatusChange事件处理。
106
107**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
108
109**系统能力:** SystemCapability.ArkUI.ArkUI.Full
110
111**参数:**
112
113| 参数名 | 类型 | 必填 | 说明 |
114| -------- | -------- | -------- | -------- |
115| status | [HoverModeStatus](#hovermodestatus) | 是 | 折叠屏进入或退出悬停模式时触发的回调函数。 |
116
117## HoverModeStatus
118
119设备或应用的折叠、旋转、窗口状态信息。
120
121**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
122
123**系统能力:** SystemCapability.ArkUI.ArkUI.Full
124
125| 名称 | 类型 | 必填 | 说明 |
126| -------- | -------- | -------- | -------- |
127| foldStatus | [display.FoldStatus](../js-apis-display.md#foldstatus10) | 是 | 设备的折叠状态。 |
128| isHoverMode | boolean | 是 | app当前是否处于悬停态。 |
129| appRotation | number | 是 | 应用旋转角度。 |
130| windowStatusType | [window.WindowStatusType](../js-apis-window.md#windowstatustype11) | 是 | 窗口模式。 |
131
132## ExtraRegionPosition
133
134扩展区域位置信息。
135
136**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
137
138**系统能力:** SystemCapability.ArkUI.ArkUI.Full
139
140| 名称 | 值 | 说明 |
141| -------- | -------- | -------- |
142| TOP | 1 | 扩展区域在组件上半区域。 |
143| BOTTOM | 2 | 扩展区域在组件下半区域。 |
144
145## PresetSplitRatio
146
147区域比例。
148
149**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
150
151**系统能力:** SystemCapability.ArkUI.ArkUI.Full
152
153| 名称 | 值 | 说明 |
154| -------- | -------- | -------- |
155| LAYOUT_1V1 | 1 | 1:1比例。 |
156| LAYOUT_3V2 | 1.5 | 3:2比例。 |
157| LAYOUT_2V3 | 0.6666666666666666 | 2:3比例。 |
158
159## 示例
160
161### 示例1(设置二分栏)
162
163该示例实现了折叠屏二分栏在展开态、悬停态以及折叠态的区域控制。
164
165```ts
166import { FoldSplitContainer } from '@kit.ArkUI';
167
168@Entry
169@Component
170struct TwoColumns {
171  @Builder
172  privateRegion() {
173    Text("Primary")
174      .backgroundColor('rgba(255, 0, 0, 0.1)')
175      .fontSize(28)
176      .textAlign(TextAlign.Center)
177      .height('100%')
178      .width('100%')
179  }
180
181  @Builder
182  secondaryRegion() {
183    Text("Secondary")
184      .backgroundColor('rgba(0, 255, 0, 0.1)')
185      .fontSize(28)
186      .textAlign(TextAlign.Center)
187      .height('100%')
188      .width('100%')
189  }
190
191  build() {
192    RelativeContainer() {
193      FoldSplitContainer({
194        primary: () => {
195          this.privateRegion()
196        },
197        secondary: () => {
198          this.secondaryRegion()
199        }
200      })
201    }
202    .height('100%')
203    .width('100%')
204  }
205}
206```
207
208| 折叠态 | 展开态 | 悬停态 |
209| ----- | ------ | ------ |
210| ![](figures/foldsplitcontainer-1.png) | ![](figures/foldsplitcontainer-2.png) | ![](figures/foldsplitcontainer-3.png) |
211
212### 示例2(设置三分栏)
213
214该示例实现了折叠屏三分栏在展开态、悬停态以及折叠态的区域控制。
215
216```ts
217import { FoldSplitContainer } from '@kit.ArkUI';
218
219@Entry
220@Component
221struct ThreeColumns {
222  @Builder
223  privateRegion() {
224    Text("Primary")
225      .backgroundColor('rgba(255, 0, 0, 0.1)')
226      .fontSize(28)
227      .textAlign(TextAlign.Center)
228      .height('100%')
229      .width('100%')
230  }
231
232  @Builder
233  secondaryRegion() {
234    Text("Secondary")
235      .backgroundColor('rgba(0, 255, 0, 0.1)')
236      .fontSize(28)
237      .textAlign(TextAlign.Center)
238      .height('100%')
239      .width('100%')
240  }
241
242  @Builder
243  extraRegion() {
244    Text("Extra")
245      .backgroundColor('rgba(0, 0, 255, 0.1)')
246      .fontSize(28)
247      .textAlign(TextAlign.Center)
248      .height('100%')
249      .width('100%')
250  }
251
252  build() {
253    RelativeContainer() {
254      FoldSplitContainer({
255        primary: () => {
256          this.privateRegion()
257        },
258        secondary: () => {
259          this.secondaryRegion()
260        },
261        extra: () => {
262          this.extraRegion()
263        }
264      })
265    }
266    .height('100%')
267    .width('100%')
268  }
269}
270```
271
272| 折叠态 | 展开态 | 悬停态 |
273| ----- | ------ | ------ |
274| ![](figures/foldsplitcontainer-4.png) | ![](figures/foldsplitcontainer-5.png) | ![](figures/foldsplitcontainer-6.png) |
275
276### 示例3(展开态布局信息)
277
278该示例通过配置ExpandedRegionLayoutOptions实现折叠屏展开态的布局信息。
279
280```ts
281import {
282  FoldSplitContainer,
283  PresetSplitRatio,
284  ExtraRegionPosition,
285  ExpandedRegionLayoutOptions,
286  HoverModeRegionLayoutOptions,
287  FoldedRegionLayoutOptions
288} from '@kit.ArkUI';
289
290@Component
291struct Region {
292  @Prop title: string;
293  @BuilderParam content: () => void;
294  @Prop compBackgroundColor: string;
295
296  build() {
297    Column({ space: 8 }) {
298      Text(this.title)
299        .fontSize("24fp")
300        .fontWeight(600)
301
302      Scroll() {
303        this.content()
304      }
305      .layoutWeight(1)
306      .width("100%")
307    }
308    .backgroundColor(this.compBackgroundColor)
309    .width("100%")
310    .height("100%")
311    .padding(12)
312  }
313}
314
315const noop = () => {
316};
317
318@Component
319struct SwitchOption {
320  @Prop label: string = ""
321  @Prop value: boolean = false
322  public onChange: (checked: boolean) => void = noop;
323
324  build() {
325    Row() {
326      Text(this.label)
327      Blank()
328      Toggle({ type: ToggleType.Switch, isOn: this.value })
329        .onChange((isOn) => {
330          this.onChange(isOn);
331        })
332    }
333    .backgroundColor(Color.White)
334    .borderRadius(8)
335    .padding(8)
336    .width("100%")
337  }
338}
339
340interface RadioOptions {
341  label: string;
342  value: Object | undefined | null;
343  onChecked: () => void;
344}
345
346@Component
347struct RadioOption {
348  @Prop label: string;
349  @Prop value: Object | undefined | null;
350  @Prop options: Array<RadioOptions>;
351
352  build() {
353    Row() {
354      Text(this.label)
355      Blank()
356      Column({ space: 4 }) {
357        ForEach(this.options, (option: RadioOptions) => {
358          Row() {
359            Radio({
360              group: this.label,
361              value: JSON.stringify(option.value),
362            })
363              .checked(this.value === option.value)
364              .onChange((checked) => {
365                if (checked) {
366                  option.onChecked();
367                }
368              })
369            Text(option.label)
370          }
371        })
372      }
373      .alignItems(HorizontalAlign.Start)
374    }
375    .alignItems(VerticalAlign.Top)
376    .backgroundColor(Color.White)
377    .borderRadius(8)
378    .padding(8)
379    .width("100%")
380  }
381}
382
383@Entry
384@Component
385struct Index {
386  @State expandedRegionLayoutOptions: ExpandedRegionLayoutOptions = {
387    horizontalSplitRatio: PresetSplitRatio.LAYOUT_3V2,
388    verticalSplitRatio: PresetSplitRatio.LAYOUT_1V1,
389    isExtraRegionPerpendicular: true,
390    extraRegionPosition: ExtraRegionPosition.TOP
391  };
392  @State foldingRegionLayoutOptions: HoverModeRegionLayoutOptions = {
393    horizontalSplitRatio: PresetSplitRatio.LAYOUT_3V2,
394    showExtraRegion: false,
395    extraRegionPosition: ExtraRegionPosition.TOP
396  };
397  @State foldedRegionLayoutOptions: FoldedRegionLayoutOptions = {
398    verticalSplitRatio: PresetSplitRatio.LAYOUT_1V1
399  };
400
401  @Builder
402  MajorRegion() {
403    Region({
404      title: "折叠态配置",
405      compBackgroundColor: "rgba(255, 0, 0, 0.1)",
406    }) {
407      Column({ space: 4 }) {
408        RadioOption({
409          label: "折叠态垂直高度度比",
410          value: this.foldedRegionLayoutOptions.verticalSplitRatio,
411          options: [
412            {
413              label: "1:1",
414              value: PresetSplitRatio.LAYOUT_1V1,
415              onChecked: () => {
416                this.foldedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_1V1
417              }
418            },
419            {
420              label: "2:3",
421              value: PresetSplitRatio.LAYOUT_2V3,
422              onChecked: () => {
423                this.foldedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_2V3
424              }
425            },
426            {
427              label: "3:2",
428              value: PresetSplitRatio.LAYOUT_3V2,
429              onChecked: () => {
430                this.foldedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_3V2
431              }
432            },
433            {
434              label: "未定义",
435              value: undefined,
436              onChecked: () => {
437                this.foldedRegionLayoutOptions.verticalSplitRatio = undefined
438              }
439            }
440          ]
441        })
442      }
443      .constraintSize({ minHeight: "100%" })
444    }
445  }
446
447  @Builder
448  MinorRegion() {
449    Region({
450      title: "悬停态配置",
451      compBackgroundColor: "rgba(0, 255, 0, 0.1)"
452    }) {
453      Column({ space: 4 }) {
454        RadioOption({
455          label: "悬停态水平宽度比",
456          value: this.foldingRegionLayoutOptions.horizontalSplitRatio,
457          options: [
458            {
459              label: "1:1",
460              value: PresetSplitRatio.LAYOUT_1V1,
461              onChecked: () => {
462                this.foldingRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_1V1
463              }
464            },
465            {
466              label: "2:3",
467              value: PresetSplitRatio.LAYOUT_2V3,
468              onChecked: () => {
469                this.foldingRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_2V3
470              }
471            },
472            {
473              label: "3:2",
474              value: PresetSplitRatio.LAYOUT_3V2,
475              onChecked: () => {
476                this.foldingRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_3V2
477              }
478            },
479            {
480              label: "未定义",
481              value: undefined,
482              onChecked: () => {
483                this.foldingRegionLayoutOptions.horizontalSplitRatio = undefined
484              }
485            },
486          ]
487        })
488
489        SwitchOption({
490          label: "悬停态是否显示扩展区",
491          value: this.foldingRegionLayoutOptions.showExtraRegion,
492          onChange: (checked) => {
493            this.foldingRegionLayoutOptions.showExtraRegion = checked;
494          }
495        })
496
497        if (this.foldingRegionLayoutOptions.showExtraRegion) {
498          RadioOption({
499            label: "悬停态扩展区位置",
500            value: this.foldingRegionLayoutOptions.extraRegionPosition,
501            options: [
502              {
503                label: "顶部",
504                value: ExtraRegionPosition.TOP,
505                onChecked: () => {
506                  this.foldingRegionLayoutOptions.extraRegionPosition = ExtraRegionPosition.TOP
507                }
508              },
509              {
510                label: "底部",
511                value: ExtraRegionPosition.BOTTOM,
512                onChecked: () => {
513                  this.foldingRegionLayoutOptions.extraRegionPosition = ExtraRegionPosition.BOTTOM
514                }
515              },
516              {
517                label: "未定义",
518                value: undefined,
519                onChecked: () => {
520                  this.foldingRegionLayoutOptions.extraRegionPosition = undefined
521                }
522              },
523            ]
524          })
525        }
526      }
527      .constraintSize({ minHeight: "100%" })
528    }
529  }
530
531  @Builder
532  ExtraRegion() {
533    Region({
534      title: "展开态配置",
535      compBackgroundColor: "rgba(0, 0, 255, 0.1)"
536    }) {
537      Column({ space: 4 }) {
538        RadioOption({
539          label: "展开态水平宽度比",
540          value: this.expandedRegionLayoutOptions.horizontalSplitRatio,
541          options: [
542            {
543              label: "1:1",
544              value: PresetSplitRatio.LAYOUT_1V1,
545              onChecked: () => {
546                this.expandedRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_1V1
547              }
548            },
549            {
550              label: "2:3",
551              value: PresetSplitRatio.LAYOUT_2V3,
552              onChecked: () => {
553                this.expandedRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_2V3
554              }
555            },
556            {
557              label: "3:2",
558              value: PresetSplitRatio.LAYOUT_3V2,
559              onChecked: () => {
560                this.expandedRegionLayoutOptions.horizontalSplitRatio = PresetSplitRatio.LAYOUT_3V2
561              }
562            },
563            {
564              label: "未定义",
565              value: undefined,
566              onChecked: () => {
567                this.expandedRegionLayoutOptions.horizontalSplitRatio = undefined
568              }
569            },
570          ]
571        })
572
573        RadioOption({
574          label: "展开态垂直高度度比",
575          value: this.expandedRegionLayoutOptions.verticalSplitRatio,
576          options: [
577            {
578              label: "1:1",
579              value: PresetSplitRatio.LAYOUT_1V1,
580              onChecked: () => {
581                this.expandedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_1V1
582              }
583            },
584            {
585              label: "2:3",
586              value: PresetSplitRatio.LAYOUT_2V3,
587              onChecked: () => {
588                this.expandedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_2V3
589              }
590            },
591            {
592              label: "3:2",
593              value: PresetSplitRatio.LAYOUT_3V2,
594              onChecked: () => {
595                this.expandedRegionLayoutOptions.verticalSplitRatio = PresetSplitRatio.LAYOUT_3V2
596              }
597            },
598            {
599              label: "未定义",
600              value: undefined,
601              onChecked: () => {
602                this.expandedRegionLayoutOptions.verticalSplitRatio = undefined
603              }
604            }
605          ]
606        })
607
608        SwitchOption({
609          label: "展开态扩展区是否上下贯穿",
610          value: this.expandedRegionLayoutOptions.isExtraRegionPerpendicular,
611          onChange: (checked) => {
612            this.expandedRegionLayoutOptions.isExtraRegionPerpendicular = checked;
613          }
614        })
615
616        if (!this.expandedRegionLayoutOptions.isExtraRegionPerpendicular) {
617          RadioOption({
618            label: "展开态扩展区位置",
619            value: this.expandedRegionLayoutOptions.extraRegionPosition,
620            options: [
621              {
622                label: "顶部",
623                value: ExtraRegionPosition.TOP,
624                onChecked: () => {
625                  this.expandedRegionLayoutOptions.extraRegionPosition = ExtraRegionPosition.TOP
626                }
627              },
628              {
629                label: "底部",
630                value: ExtraRegionPosition.BOTTOM,
631                onChecked: () => {
632                  this.expandedRegionLayoutOptions.extraRegionPosition = ExtraRegionPosition.BOTTOM
633                }
634              },
635              {
636                label: "未定义",
637                value: undefined,
638                onChecked: () => {
639                  this.expandedRegionLayoutOptions.extraRegionPosition = undefined
640                }
641              },
642            ]
643          })
644        }
645      }
646      .constraintSize({ minHeight: "100%" })
647    }
648  }
649
650  build() {
651    Column() {
652      FoldSplitContainer({
653        primary: () => {
654          this.MajorRegion()
655        },
656        secondary: () => {
657          this.MinorRegion()
658        },
659        extra: () => {
660          this.ExtraRegion()
661        },
662        expandedLayoutOptions: this.expandedRegionLayoutOptions,
663        hoverModeLayoutOptions: this.foldingRegionLayoutOptions,
664        foldedLayoutOptions: this.foldedRegionLayoutOptions,
665      })
666    }
667    .width("100%")
668    .height("100%")
669  }
670}
671```
672
673| 折叠态 | 展开态 | 悬停态 |
674| ----- | ------ | ------ |
675| ![](figures/foldsplitcontainer-7.png) | ![](figures/foldsplitcontainer-8.png) | ![](figures/foldsplitcontainer-11.png) |
676|                                       | ![](figures/foldsplitcontainer-9.png) | ![](figures/foldsplitcontainer-12.png) |
677|                                       | ![](figures/foldsplitcontainer-10.png) | ![](figures/foldsplitcontainer-13.png) |
678