ListView
<ListView>
is a UI component that shows items in a vertically scrolling list.
To set how the list shows individual items, you can use the <v-template>
component.
Using a ListView requires some special attention due to the complexity of the native implementations, with custom item templates, bindings and so on.
The NativeScript modules provides a custom component which simplifies the way native ListView is used.
The ListView’s item template can contain only a single root view container. |
<ListView [items]="items" (itemTap)="onItemTap($event)" class="list-group">
<ng-template let-item="item" let-i="index" let-odd="odd" let-even="even">
<!-- The item template can only have a single root view container (e.g. GridLayout, StackLayout, etc.)-->
<GridLayout>
<label [text]="item.name" class="list-group-item"></label>
</GridLayout>
</ng-template>
</ListView>
import { Component, Injectable, OnInit } from '@angular/core'
import { ItemEventData } from '@nativescript/core'
@Component({
moduleId: module.id,
templateUrl: './usage.component.html'
})
export class ListViewUsageComponent implements OnInit {
items: Array<Item>
constructor(private _itemService: ItemService) {}
ngOnInit(): void {
this.items = this._itemService.getItems()
}
onItemTap(args: ItemEventData) {
console.log(
`Index: ${args.index}; View: ${args.view} ; Item: ${this.items[args.index]}`
)
}
}
@Injectable({
providedIn: 'root'
})
export class ItemService {
private items = new Array<Item>(
{ id: 1, name: 'Ter Stegen', role: 'Goalkeeper' },
{ id: 3, name: 'Piqué', role: 'Defender' },
{ id: 4, name: 'I. Rakitic', role: 'Midfielder' },
{ id: 5, name: 'Sergio', role: 'Midfielder' },
{ id: 6, name: 'Denis Suárez', role: 'Midfielder' },
{ id: 7, name: 'Arda', role: 'Midfielder' },
{ id: 8, name: 'A. Iniesta', role: 'Midfielder' },
{ id: 9, name: 'Suárez', role: 'Forward' },
{ id: 10, name: 'Messi', role: 'Forward' },
{ id: 11, name: 'Neymar', role: 'Forward' },
{ id: 12, name: 'Rafinha', role: 'Midfielder' },
{ id: 13, name: 'Cillessen', role: 'Goalkeeper' },
{ id: 14, name: 'Mascherano', role: 'Defender' },
{ id: 17, name: 'Paco Alcácer', role: 'Forward' },
{ id: 18, name: 'Jordi Alba', role: 'Defender' },
{ id: 19, name: 'Digne', role: 'Defender' },
{ id: 20, name: 'Sergi Roberto', role: 'Midfielder' },
{ id: 21, name: 'André Gomes', role: 'Midfielder' },
{ id: 22, name: 'Aleix Vidal', role: 'Midfielder' },
{ id: 23, name: 'Umtiti', role: 'Defender' },
{ id: 24, name: 'Mathieu', role: 'Defender' },
{ id: 25, name: 'Masip', role: 'Goalkeeper' }
)
getItems(): Array<Item> {
return this.items
}
getItem(id: number): Item {
return this.items.filter(item => item.id === id)[0]
}
}
export class Item {
constructor(public id: number, public name: string, public role: string) {}
<ListView
[items]="items"
class="list-group"
[itemTemplateSelector]="templateSelector"
row="0"
>
<ng-template nsTemplateKey="red" let-item="item" let-i="index">
<GridLayout>
<label [text]="item.name" backgroundColor="red" color="white"></label>
</GridLayout>
</ng-template>
<ng-template nsTemplateKey="green" let-item="item" let-i="index">
<GridLayout>
<label [text]="item.name" backgroundColor="green" color="yellow"></label>
</GridLayout>
</ng-template>
</ListView>
import { Component, Input, OnChanges, SimpleChanges, OnInit } from '@angular/core'
import { ItemService, Item } from '../usage/usage.service'
import { ItemEventData } from '@nativescript/core'
@Component({
moduleId: module.id,
templateUrl: './tips-and-tricks.component.html'
})
export class ListViewTipsComponent implements OnInit {
items: Array<Item>
constructor(private _itemService: ItemService) {}
ngOnInit(): void {
this.items = this._itemService.getItems()
}
onItemTap(args: ItemEventData) {
console.log(
`Index: ${args.index}; View: ${args.view} ; Name: ${this.items[args.index].name}`
)
}
templateSelector(item: Item, index: number, items: any) {
return index % 2 === 0 ? 'red' : 'green'
}
}
Name | Type | Description |
---|---|---|
|
|
Gets or set the items collection of the |
|
|
A function that returns the appropriate ket template based on the data item. |
|
|
Gets or set the list of item templates for the item template selector. |
|
|
Gets or set the items separator line color of the ListView. |
|
|
Gets or set row height of the ListView. |
|
|
Gets or set the estimated height of rows in the ListView. Default value: 44px |
<ListView
items="{{ titlesArray }}"
loaded="{{ onListViewLoaded }}"
itemTap="onItemTap"
loadMoreItems="onLoadMoreItems"
separatorColor="orangered"
rowHeight="50"
class="list-group"
id="listView"
>
<ListView.itemTemplate>
<!-- The item template can only have a single root view container (e.g. GriLayout, StackLayout, etc.) -->
<StackLayout class="list-group-item">
<Label text="{{ title || 'Downloading...' }}" textWrap="true" class="title" />
</StackLayout>
</ListView.itemTemplate>
</ListView>
import {
EventData,
fromObject,
ListView,
ObservableArray,
ItemEventData,
Page
} from '@nativescript/core'
export function onNavigatingTo(args: EventData) {
const page = args.object as Page
const titlesArray = new ObservableArray([
{ title: 'The Da Vinci Code' },
{ title: 'Harry Potter and the Chamber of Secrets' },
{ title: 'The Alchemist' },
{ title: 'The Godfather' },
{ title: 'Goodnight Moon' },
{ title: 'The Hobbit' }
])
const vm = Observable()
vm.titlesArray = titlesArray
page.bindingContext = vm
}
export function onListViewLoaded(args: EventData) {
const listView = args.object as ListView
}
// The event will be raise when an item inside the ListView is tapped.
export function onItemTap(args: ItemEventData) {
const index = args.index
console.log(`Second ListView item tap ${index}`)
}
// The event will be raised when the ListView is scrolled so that the last item is visible.
// This even is intended to be used to add additional data in the ListView.
export function onLoadMoreItems(args: ItemEventData) {
if (loadMore) {
console.log('ListView -> LoadMoreItemsEvent')
setTimeout(() => {
listArray.push(
moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
)
listArray.push(
moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
)
listArray.push(
moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
)
listArray.push(
moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
)
listArray.push(
moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
)
}, 3000)
loadMore = false
}
}
Name | Type | Description |
---|---|---|
|
|
Gets or set the items collection of the |
|
|
A function that returns the appropriate key template based on the data item. |
|
|
Gets or set the list of item templates for the item template selector. |
|
|
Gets or set the items separator line color of the ListView. |
|
|
Gets or set row height of the ListView. |
|
|
Gets or set the estimated height of rows in the ListView. Default value: 44px |
<ListView for="item in listOfItems" @itemTap="onItemTap">
<v-template>
<!-- Shows the list item label in the default color and style. -->
<label :text="item.text" />
</v-template>
</ListView>
Instead of manually triggering the UI update with the help of ListView’s refresh method, NativeScript provides the ObservableArray. Using an ObservableArray for your listview’s items source will make its members an observable objects and adding/removing an array item will automatically update the UI. |
Important Using the ListView component inside a ScrollView or ScrollView inside the ListView’s items can lead to poor performance and can reflect the user experience. To avoid this issue, we should specify the height explicitly for the ListView in the scenario when the ListView is nested in ScrollView and the ScrollView’s height - when the component is used inside the ListView.
|
Events
Name | Description |
---|---|
|
Emitted when an item in the |
Methods
Name | Description |
---|---|
|
Forces the |
|
Scrolls the specified item with index into view. |
|
Scrolls the specified item with index into view with animation. |
|
Checks if specified items with index are visible. |