Skip to content

Commit 9570ed1

Browse files
committed
feat: listview sectioned data
1 parent 0258f2f commit 9570ed1

File tree

1 file changed

+151
-5
lines changed

1 file changed

+151
-5
lines changed

content/ui/list-view.md

Lines changed: 151 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
---
22
title: ListView
3-
description: UI component for rendering large lists using view recycling.
3+
description: UI component for rendering large lists using view recycling, with optional sticky headers, sectioned data, and an integrated search bar.
44
contributors:
55
- rigor789
66
- Ombuweb
7+
- NathanWalker
78
---
89

9-
`<ListView>` is a UI component that renders items in a vertically scrolling list, the template for the items can be defined via `itemTemplate` (or multiple templates via `itemTemplates` - more on that below). The ListView only renders the visible items, as the user scrolls, new items render by reusing a no-longer-visible item's view&mdash;this is usually referred to as view-recycling.
10+
`<ListView>` is a UI component that renders items in a vertically scrolling list. The template for the items can be defined via `itemTemplate` (or multiple templates via `itemTemplates` more on that below). The ListView only renders the visible items; as the user scrolls, new items render by reusing a no-longer-visible item's viewthis is usually referred to as view-recycling.
1011

11-
::: tip
12+
Newer versions of `ListView` (v9+) can also render **sectioned data** (for example, A–Z lists) with **sticky headers** and an **optional search bar** that can auto-hide on iOS.
1213

13-
For additional features and improved performance in certain scenarios, consider using an alternative implementation like the
14+
::: tip
15+
You can also explore
1416
[CollectionView](https://github.com/nativescript-community/ui-collectionview) from the community.
15-
1617
:::
1718

1819
<DeviceFrame type="ios">
@@ -78,6 +79,72 @@ Individual items can be rendered using a different template. For example, let's
7879
</Tab>
7980
</Tabs>
8081

82+
### Sectioned ListView with sticky headers and search
83+
84+
Starting with v9, ListView can render sectioned data with sticky headers and an optional search bar. This is useful for contact lists, country lists, or any data grouped by a key.
85+
86+
A supported data shape looks like this:
87+
88+
```ts
89+
const countries: { title: string; items: { name: string; code?: string; flag?: string }[] }[] = [
90+
{
91+
title: 'A',
92+
items: [
93+
{ name: 'Albania', code: 'AL' },
94+
],
95+
},
96+
{
97+
title: 'B',
98+
items: [
99+
{ name: 'Bahamas', code: 'BS' },
100+
],
101+
},
102+
]
103+
```
104+
105+
You can then bind this data to the ListView and enable the new props:
106+
107+
```xml
108+
<ListView
109+
items="{{ countries }}"
110+
sectioned="true"
111+
stickyHeader="true"
112+
stickyHeaderHeight="45"
113+
stickyHeaderTopPadding="false"
114+
showSearch="true"
115+
searchAutoHide="true"
116+
itemTemplateSelector="{{ itemTemplateSelector }}"
117+
stickyHeaderTemplate="
118+
<GridLayout>
119+
<Label text='{{ title }}'
120+
fontSize='18'
121+
fontWeight='bold'
122+
color='#009bff'
123+
padding='8 0 8 12'
124+
borderBottomWidth='1'
125+
borderBottomColor='#ccc'
126+
borderTopWidth='1'
127+
borderTopColor='#ccc'
128+
backgroundColor='#fff' />
129+
</GridLayout>
130+
" />
131+
```
132+
133+
In code you can listen for search changes:
134+
135+
```ts
136+
listView.on('searchChange', (args: SearchEventData) => {
137+
console.log('search text:', args.text)
138+
// apply filtering to your backing data if desired
139+
})
140+
```
141+
142+
Notes:
143+
144+
- `searchAutoHide` is currently iOS-only (it will auto-hide the search on scroll).
145+
- `stickyHeaderTemplate` accepts the same binding context as the section (`title`, etc.).
146+
- Make sure each section’s `items` array is present; empty / null sections may not render as expected.
147+
81148
## Props
82149

83150
### items
@@ -128,6 +195,71 @@ Gets or sets the available itemTemplates.
128195

129196
See [KeyedTemplate](/api/interface/KeyedTemplate).
130197

198+
### sectioned
199+
200+
```ts
201+
sectioned: boolean
202+
```
203+
204+
Enables sectioned data rendering on the `ListView`. When `true`, the ListView expects the `items` source to be an **array of sections** where each section has a `title` (or similar field) and an `items` array:
205+
206+
```ts
207+
{
208+
title: string;
209+
items: any[];
210+
}
211+
```
212+
213+
This allows the ListView to render grouped lists with headers.
214+
215+
### stickyHeader
216+
217+
```ts
218+
stickyHeader: boolean
219+
```
220+
221+
Enables sticky (pinned) headers while scrolling sectioned data. When enabled, the current section header stays at the top of the list until the next section header pushes it away.
222+
223+
### stickyHeaderTemplate
224+
225+
```ts
226+
stickyHeaderTemplate: string | KeyedTemplate
227+
```
228+
229+
Gets or sets the template used to render a section header when sticky headers are enabled. This accepts bindings from the current section (for example: `{{ title }}`).
230+
231+
### stickyHeaderHeight
232+
233+
```ts
234+
stickyHeaderHeight: number
235+
```
236+
237+
Explicit height for the sticky header. Providing this can improve measurement and scrolling performance, especially on iOS where headers update as you scroll.
238+
239+
### stickyHeaderTopPadding
240+
241+
```ts
242+
stickyHeaderTopPadding: boolean | number
243+
```
244+
245+
Controls the padding applied to the sticky header at the top. Set to `false` to disable the extra top padding; set to a number to supply an explicit padding value.
246+
247+
### showSearch
248+
249+
```ts
250+
showSearch: boolean
251+
```
252+
253+
Shows a built-in search bar above the ListView. This is useful when you want a declarative, per-list search input without adding a separate `SearchBar` component.
254+
255+
### searchAutoHide
256+
257+
```ts
258+
searchAutoHide: boolean
259+
```
260+
261+
(iOS only) When `true`, the built-in search bar will auto-hide when the user scrolls. This mirrors common iOS list behaviors.
262+
131263
### separatorColor
132264

133265
```ts
@@ -150,6 +282,8 @@ rowHeight: number
150282

151283
Gets or sets the row height of the ListView. Useful when your items have a fixed height, as the required calculations are greatly simplified and the rendering can be faster.
152284

285+
> Android: with the latest ListView improvements, row items will now react properly to spacing (padding and margin), so setting `rowHeight` alongside your layout spacing should behave more predictably across platforms.
286+
153287
### iosEstimatedRowHeight
154288

155289
Gets or sets the estimated height of rows in the ListView. Default value: `44px`
@@ -235,6 +369,18 @@ on('loadMoreItems', (args: EventData) => {
235369

236370
Emitted when the user reaches the end of the ListView. Useful for loading additional items (ie. infinite scroll).
237371

372+
### searchChange
373+
374+
```ts
375+
on('searchChange', (args: SearchEventData) => {
376+
console.log('Search text changed:', args.text)
377+
})
378+
```
379+
380+
Emitted when the built-in search bar text changes. You can use this to filter the underlying list data, or to drive remote searches.
381+
382+
See `SearchEventData` in the API reference for the shape of the event.
383+
238384
## Native component
239385

240386
- Android: [`android.widget.ListView`](https://developer.android.com/reference/android/widget/ListView.html)

0 commit comments

Comments
 (0)