• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ListItemGroup
2
3<!--Kit: ArkUI-->
4<!--Subsystem: ArkUI-->
5<!--Owner: @yylong-->
6<!--Designer: @yylong-->
7<!--Tester: @liuzhenshuo-->
8<!--Adviser: @HelloCrease-->
9
10该组件用来展示列表item分组,宽度默认充满[List](ts-container-list.md)组件,必须配合List组件来使用。
11
12> **说明:**
13>
14> - 该组件从API version 9开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
15> - 该组件的父组件只能是[List](ts-container-list.md)。
16> - ListItemGroup组件不支持设置[通用属性aspectRatio](ts-universal-attributes-layout-constraints.md#aspectratio)。
17> - 当ListItemGroup的父组件List的listDirection属性为Axis.Vertical时,设置[通用属性height](ts-universal-attributes-size.md#height)属性不生效。ListItemGroup的高度为header高度、footer高度和所有ListItem布局后总高度之和。
18> - 当父组件List的listDirection属性为Axis.Horizontal时,设置[通用属性width](ts-universal-attributes-size.md#width)属性不生效。ListItemGroup的宽度为header宽度、footer宽度和所有ListItem布局后总宽度之和。
19> - 当前ListItemGroup内部的ListItem组件不支持编辑、拖拽功能,即ListItem组件的editable属性不生效。
20> - ListItemGroup使用direction属性设置布局方向不生效,ListItemGroup组件布局方向跟随父容器List组件的布局方向。
21
22## 子组件
23
24包含[ListItem](ts-container-listitem.md)子组件。支持通过渲染控制类型([if/else](../../../ui/state-management/arkts-rendering-control-ifelse.md)、[ForEach](../../../ui/state-management/arkts-rendering-control-foreach.md)、[LazyForEach](../../../ui/state-management/arkts-rendering-control-lazyforeach.md)和[Repeat](../../../ui/state-management/arkts-new-rendering-control-repeat.md))动态生成子组件,更推荐使用LazyForEach或Repeat以优化性能。
25
26
27## 接口
28
29ListItemGroup(options?: ListItemGroupOptions)
30
31创建ListItemGroup组件。
32
33**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
34
35**系统能力:** SystemCapability.ArkUI.ArkUI.Full
36
37**参数:**
38
39| 参数名 | 类型 | 必填 | 说明 |
40| -------- | -------- | -------- | -------- |
41| options |  [ListItemGroupOptions](#listitemgroupoptions对象说明)| 否 | 列表item分组组件参数。 |
42
43## ListItemGroupOptions对象说明
44
45ListItemGroup组件参数。
46
47**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
48
49**系统能力:** SystemCapability.ArkUI.ArkUI.Full
50
51| 名称              | 类型                                            | 只读 | 可选   | 说明                                                     |
52| ------------------- | --------------------------------------------------- | ---- | -- | ------------------------------------------------------------ |
53| header              | [CustomBuilder](ts-types.md#custombuilder8) &nbsp;   | 否   | 是 | 设置ListItemGroup头部组件。<br/>**说明:**<br/>可以放单个子组件或不放子组件。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。               |
54| headerComponent<sup>13+</sup>              | [ComponentContent](../js-apis-arkui-ComponentContent.md)       | 否   | 是 | 使用ComponentContent类型参数设置ListItemGroup头部组件。<br/>**说明:**<br/>可以放单个子组件或不放子组件。 该参数的优先级高于参数header。即同时设置header和headerComponent时,以headerComponent设置的值为准。<br/>同一个headerComponent不推荐同时给不同的ListItemGroup使用,否则会导致显示问题。<br/>**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。              |
55| footer              | [CustomBuilder](ts-types.md#custombuilder8) &nbsp;     | 否   | 是 | 设置ListItemGroup尾部组件。<br/>**说明:**<br/>可以放单个子组件或不放子组件。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。               |
56| footerComponent<sup>13+</sup>              | [ComponentContent](../js-apis-arkui-ComponentContent.md)       | 否   | 是 | 使用ComponentContent类型参数设置ListItemGroup尾部组件。<br/>**说明:**<br/>可以放单个子组件或不放子组件。该参数的优先级高于参数footer。 即同时设置footer和footerComponent时,以footerComponent设置的值为准。<br/>同一个footerComponent不推荐同时给不同的ListItemGroup使用,否则会导致显示问题。<br/>**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。                           |
57| space               | number&nbsp;\|&nbsp;string                          | 否   | 是 | 列表项间距。只作用于ListItem与ListItem之间,不作用于header与ListItem、footer与ListItem之间。<br/>默认值:0<br/>单位:vp <br/>**说明:**<br/>设置为负数或者大于等于List内容区长度时,按默认值显示。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。  |
58| style<sup>10+</sup> | [ListItemGroupStyle](#listitemgroupstyle10枚举说明) | 否   | 是 | 设置List组件卡片样式。<br/>默认值:ListItemGroupStyle.NONE<br/>设置为ListItemGroupStyle.NONE时无样式。<br/>设置为ListItemGroupStyle.CARD时,建议配合[ListItem](ts-container-listitem.md)的ListItemStyle.CARD同时使用,显示默认卡片样式。 <br/>卡片样式下,ListItemGroup默认规格:左右外边距12vp,上下左右内边距4vp。<br/>卡片样式下,为卡片内的列表选项提供了默认的focus、hover、press、selected和disable样式。<br/>**说明:**<br/>当前卡片模式下,使用默认Axis.Vertical排列方向,如果listDirection属性设置为Axis.Horizontal,会导致显示混乱;List属性alignListItem默认为ListItemAlign.Center,居中对齐显示。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 |
59
60## 属性
61
62### divider
63
64divider(value: [ListDividerOptions](ts-container-list.md#listdivideroptions18对象说明) | null)
65
66设置ListItem分割线样式,默认无分割线。
67
68strokeWidth, startMargin和endMargin不支持设置百分比。
69
70ListItem设置[多态样式](ts-universal-attributes-polymorphic-style.md)时,被按压的子组件上下的分割线不绘制。
71
72**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
73
74**系统能力:** SystemCapability.ArkUI.ArkUI.Full
75
76**参数:**
77
78| 参数名 | 类型                                                         | 必填 | 说明                                                         |
79| ------ | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
80| value  | [ListDividerOptions](ts-container-list.md#listdivideroptions18对象说明)&nbsp;\|&nbsp;null | 是   | ListItem分割线样式。<br/> 默认值:null |
81
82### childrenMainSize<sup>12+</sup>
83
84childrenMainSize(value: ChildrenMainSize)
85
86设置ListItemGroup组件的子组件在主轴方向的大小信息。
87
88**说明:**
89>
90> - 必须同时给所在的List组件设置childrenMainSize属性才可以正常生效。
91
92**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
93
94**系统能力:** SystemCapability.ArkUI.ArkUI.Full
95
96**参数:**
97
98| 参数名     | 类型   | 必填 | 说明                            |
99| ---------- | ------ | ---- | ------------------------------- |
100| value | [ChildrenMainSize](ts-container-scrollable-common.md#childrenmainsize12对象说明) | 是   | 该对象用来维护子组件在主轴方向的大小信息。|
101
102## ListItemGroupStyle<sup>10+</sup>枚举说明
103
104List组件卡片样式枚举。
105
106**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
107
108**系统能力:** SystemCapability.ArkUI.ArkUI.Full
109
110| 名称 | 值  | 说明             |
111| ---- | ---- | ------------------ |
112| NONE | 0 | 无样式。           |
113| CARD | 1 | 显示默认卡片样式。 |
114
115
116
117## 示例
118
119### 示例1(设置吸顶/吸底)
120
121该示例通过stick实现了Header吸顶和Footer吸底的效果。
122
123ListDataSource实现了LazyForEach数据源接口[IDataSource](ts-rendering-control-lazyforeach.md#idatasource),用于通过LazyForEach给List和ListItemGroup提供子组件。
124
125<!--code_no_check-->
126```ts
127// ListDataSource.ets
128export class TimeTableDataSource implements IDataSource {
129  private list: TimeTable[] = [];
130  private listeners: DataChangeListener[] = [];
131
132  constructor(list: TimeTable[]) {
133    this.list = list;
134  }
135
136  totalCount(): number {
137    return this.list.length;
138  }
139
140  getData(index: number): TimeTable {
141    return this.list[index];
142  }
143
144  registerDataChangeListener(listener: DataChangeListener): void {
145    if (this.listeners.indexOf(listener) < 0) {
146      this.listeners.push(listener);
147    }
148  }
149
150  unregisterDataChangeListener(listener: DataChangeListener): void {
151    const pos = this.listeners.indexOf(listener);
152    if (pos >= 0) {
153      this.listeners.splice(pos, 1);
154    }
155  }
156
157  // 通知控制器数据变化
158  notifyDataChange(index: number): void {
159    this.listeners.forEach(listener => {
160      listener.onDataChange(index);
161    });
162  }
163
164  // 修改第一个元素
165  public change1stItem(temp: TimeTable): void {
166    this.list[0] = temp;
167    this.notifyDataChange(0);
168  }
169}
170
171export class ProjectsDataSource implements IDataSource {
172  private list: string[] = [];
173
174  constructor(list: string[]) {
175    this.list = list;
176  }
177
178  totalCount(): number {
179    return this.list.length;
180  }
181
182  getData(index: number): string {
183    return this.list[index];
184  }
185
186  registerDataChangeListener(listener: DataChangeListener): void {
187  }
188
189  unregisterDataChangeListener(listener: DataChangeListener): void {
190  }
191}
192
193export interface TimeTable {
194  title: string;
195  projects: string[];
196}
197```
198
199<!--code_no_check-->
200```ts
201// xxx.ets
202import { TimeTable, ProjectsDataSource, TimeTableDataSource } from './ListDataSource';
203@Entry
204@Component
205struct ListItemGroupExample {
206  itemGroupArray: TimeTableDataSource = new TimeTableDataSource([]);
207
208  aboutToAppear(): void {
209    let timeTable: TimeTable[] = [
210      {
211        title: '星期一',
212        projects: ['语文', '数学', '英语']
213      },
214      {
215        title: '星期二',
216        projects: ['物理', '化学', '生物']
217      },
218      {
219        title: '星期三',
220        projects: ['历史', '地理', '政治']
221      },
222      {
223        title: '星期四',
224        projects: ['美术', '音乐', '体育']
225      }
226    ];
227    this.itemGroupArray = new TimeTableDataSource(timeTable);
228  }
229
230  @Builder
231  itemHead(text: string) {
232    Text(text)
233      .fontSize(20)
234      .backgroundColor(0xAABBCC)
235      .width('100%')
236      .padding(10)
237  }
238
239  @Builder
240  itemFoot(num: number) {
241    Text('共' + num + '节课')
242      .fontSize(16)
243      .backgroundColor(0xAABBCC)
244      .width('100%')
245      .padding(5)
246  }
247
248  build() {
249    Column() {
250      List({ space: 20 }) {
251        LazyForEach(this.itemGroupArray, (item: TimeTable) => {
252          ListItemGroup({ header: this.itemHead(item.title), footer: this.itemFoot(item.projects.length) }) {
253            LazyForEach(new ProjectsDataSource(item.projects), (project: string) => {
254              ListItem() {
255                Text(project)
256                  .width('100%')
257                  .height(100)
258                  .fontSize(20)
259                  .textAlign(TextAlign.Center)
260                  .backgroundColor(0xFFFFFF)
261              }
262            }, (item: string) => item)
263          }
264          .divider({ strokeWidth: 1, color: Color.Blue }) // 每行之间的分界线
265        })
266      }
267      .width('90%')
268      .sticky(StickyStyle.Header | StickyStyle.Footer)
269      .scrollBar(BarState.Off)
270    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 5 })
271  }
272}
273```
274
275![zh-cn_image_0000001219864159](figures/zh-cn_image_listitemgroup.gif)
276
277### 示例2(设置卡片样式)
278
279该示例展示了ListItemGroup的卡片样式效果。
280
281```ts
282// xxx.ets
283@Entry
284@Component
285struct ListItemGroupExample2 {
286  private arr: ArrObject[] = [
287    {
288      style: ListItemGroupStyle.CARD,
289      itemStyles: [ListItemStyle.CARD, ListItemStyle.CARD, ListItemStyle.CARD]
290    },
291    {
292      style: ListItemGroupStyle.CARD,
293      itemStyles: [ListItemStyle.CARD, ListItemStyle.CARD, ListItemStyle.NONE]
294    },
295    {
296      style: ListItemGroupStyle.CARD,
297      itemStyles: [ListItemStyle.CARD, ListItemStyle.NONE, ListItemStyle.CARD]
298    },
299    {
300      style: ListItemGroupStyle.NONE,
301      itemStyles: [ListItemStyle.CARD, ListItemStyle.CARD, ListItemStyle.NONE]
302    }
303  ];
304
305  build() {
306    Column() {
307      List({ space: '4vp', initialIndex: 0 }) {
308        ForEach(this.arr, (item: ArrObject, index?: number) => {
309          ListItemGroup({ style: item.style }) {
310            ForEach(item.itemStyles, (itemStyle: number, itemIndex?: number) => {
311              ListItem({ style: itemStyle }) {
312                if (index != undefined && itemIndex != undefined) {
313                  Text('第' + (index + 1) + '个Group中第' + (itemIndex + 1) + '个item')
314                    .width('100%')
315                    .textAlign(TextAlign.Center)
316                }
317              }
318            }, (item: string) => item)
319          }
320        })
321      }
322      .width('100%')
323      .multiSelectable(true)
324      .backgroundColor(0xDCDCDC)
325    }
326    .width('100%')
327    .padding({ top: 5 })
328  }
329}
330
331interface ArrObject {
332  style: number;
333  itemStyles: number[];
334}
335```
336![ListItemGroupStyle](figures/listItemGroup2.jpeg)
337
338### 示例3(设置Header/Footer339
340该示例通过ComponentContent设置Header/Footer341
342<!--code_no_check-->
343```ts
344// xxx.ets
345import { ComponentContent } from '@kit.ArkUI';
346import { TimeTable, ProjectsDataSource, TimeTableDataSource } from './ListDataSource';
347
348class HeadBuilderParams {
349  text: string | Resource;
350  constructor(text: string | Resource) {
351    this.text = text;
352  }
353}
354
355class FootBuilderParams {
356  num: number | Resource;
357  constructor(num: number | Resource) {
358    this.num = num;
359  }
360}
361
362@Builder
363function itemHead(params: HeadBuilderParams) {
364  Text(params.text)
365    .fontSize(20)
366    .height('48vp')
367    .width('100%')
368    .padding(10)
369    .backgroundColor($r('sys.color.background_tertiary'))
370}
371
372@Builder
373function itemFoot(params: FootBuilderParams) {
374  Text('共' + params.num.toString() + '节课')
375    .fontSize(20)
376    .height('48vp')
377    .width('100%')
378    .padding(10)
379    .backgroundColor($r('sys.color.background_tertiary'))
380}
381
382@Component
383struct MyItemGroup {
384  item: TimeTable = { title: '', projects: [] };
385  header?: ComponentContent<HeadBuilderParams> = undefined;
386  footer?: ComponentContent<FootBuilderParams> = undefined;
387  headerParam = new HeadBuilderParams(this.item.title);
388  footerParam = new FootBuilderParams(this.item.projects.length);
389  itemArr: ProjectsDataSource = new ProjectsDataSource([]);
390
391  aboutToAppear(): void {
392    this.header = new ComponentContent(this.getUIContext(), wrapBuilder(itemHead), this.headerParam);
393    this.footer = new ComponentContent(this.getUIContext(), wrapBuilder(itemFoot), this.footerParam);
394    this.itemArr = new ProjectsDataSource(this.item.projects);
395  }
396  GetHeader() {
397    this.header?.update(new HeadBuilderParams(this.item.title));
398    return this.header;
399  }
400
401  GetFooter() {
402    this.footer?.update(new FootBuilderParams(this.item.projects.length));
403    return this.footer;
404  }
405
406  build() {
407    ListItemGroup({
408      headerComponent: this.GetHeader(),
409      footerComponent: this.GetFooter()
410    }) {
411      LazyForEach(this.itemArr, (project: string) => {
412        ListItem() {
413          Text(project)
414            .width('100%')
415            .height(100)
416            .fontSize(20)
417            .textAlign(TextAlign.Center)
418        }
419      }, (item: string) => item)
420    }
421    .divider({ strokeWidth: 1, color: Color.Blue }) // 每行之间的分界线
422  }
423}
424
425@Entry
426@Component
427struct ListItemGroupExample {
428  itemGroupArray: TimeTableDataSource = new TimeTableDataSource([]);
429  aboutToAppear(): void {
430    let timeTable: TimeTable[] = [
431      {
432        title: '星期一',
433        projects: ['语文', '数学', '英语']
434      },
435      {
436        title: '星期二',
437        projects: ['物理', '化学', '生物']
438      },
439      {
440        title: '星期三',
441        projects: ['历史', '地理', '政治', '体育']
442      },
443      {
444        title: '星期四',
445        projects: ['美术', '音乐']
446      }
447    ];
448    this.itemGroupArray = new TimeTableDataSource(timeTable);
449  }
450
451  build() {
452    Column() {
453      Button('update').width(100).height(50).onClick(() => {
454        this.itemGroupArray.change1stItem({
455          title: '更新后的星期一',
456          projects: ['语文', '物理', '历史', '美术']
457        });
458      })
459      List({ space: 20 }) {
460        LazyForEach(this.itemGroupArray, (item: TimeTable) => {
461          MyItemGroup({ item: item })
462        }, (item: TimeTable) => item.title) // LazyForEach依赖键值判断是否刷新子组件
463      }
464      .layoutWeight(1)
465      .sticky(StickyStyle.Header | StickyStyle.Footer)
466      .scrollBar(BarState.Off)
467    }
468    .backgroundColor($r('sys.color.background_primary'))
469  }
470}
471```
472
473![zh-cn_image_listitemgroup_example03](figures/zh-cn_image_listitemgroup_example03.gif)