Tabris.js Widgets: CollectionView
This widget creates a scrollable list of elements with equal intervals between them. CollectionView can have more than one column, making it look like an HTML element. But all cells are distributed equally between columns, so it is very tricky to create real tables using CollectionView. In most cases, it is better to stick with only one column, especially given the fact that most mobile devices have relatively small screens.
Static text lists are not the only purpose of this widget – you can fill it up with Buttons and place it inside a Drawer to create application navigation, or use ImageViews to make a gallery. Don’t confuse it with ScrollView if you are looking for an internal scroll (the one you can get “overflow: scroll;” CSS property in HTML) because CollectionView can’t provide such functionality.
Here is a simple example of the widget in JS syntax:
1 2 3 4 5 |
import { CollectionView, contentView, TextView } from 'tabris'; new CollectionView({ left: 0, top: 0, right: 0, bottom: 0, }).appendTo(contentView); |
It is empty and pretty meaningless without content, so let’s find out how to fill it:
- First, you need the
createCell
property. It defines a callback function that will be used for creating a new cell. There are no “real” cells where you put content, but as explained earlier, the individual widgets serve as cells. For example, if you want a CollectionView filled with Buttons, Buttons will serve as cells. Take a look at the example below, and everything will make sense. - Then fill the cell widgets with content based on cell index. It is done with help of
updateCell
property.
Let’s fill the ContentView from above with some text fields:
1 2 3 4 5 6 7 8 9 10 11 12 |
import { CollectionView, contentView, TextView } from 'tabris'; const items = ['Apple', 'Banana', 'Cherry']; new CollectionView({ left: 0, top: 0, right: 0, bottom: 0, itemCount: items.length, createCell: () => new TextView(), updateCell: (view, index) => { view.text = items[index]; } }).appendTo(contentView); |
And here is a bit more complicated, but better-looking example in JSX syntax. Scan the QR-code below using Tabris.js Developer App to see the code in action!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import { CollectionView, Composite, ImageView, TextView, contentView } from 'tabris'; const people = [ { firstName: 'Holger', lastName: 'Staudacher' }, { firstName: 'Ian', lastName: 'Bull' }, { firstName: 'Jochen', lastName: 'Krause' }, { firstName: 'Jordi', lastName: 'Böhme López' }, { firstName: 'Markus', lastName: 'Knauer' }, { firstName: 'Moritz', lastName: 'Post' }, { firstName: 'Ralf', lastName: 'Sternberg' }, { firstName: 'Tim', lastName: 'Buschtöns' } ]; contentView.append( <CollectionView stretch itemCount={people.length} cellHeight={256} createCell={createCell} updateCell={updateCell} /> ); /** @returns {Composite} */ function createCell() { return ( <Composite> <ImageView top={16} centerX={0} width={200} height={200} /> <TextView left={30} top='prev() 16' right={30} alignment='centerX' /> </Composite> ); } /** * @param {Composite} cell * @param {number} index */ function updateCell(cell, index) { cell.find(ImageView).only().image = `resources/${people[index].firstName.toLowerCase()}.jpg`; cell.find(TextView).only().text = people[index].firstName; } |
As you may have noticed, syntactically dividing createCell() and updateCell() functions, you can make your code pretty readable and good-looking.
Just like most of Tabris widgets, CollectionView is single-purposed and simple-looking but serves as a powerful tool if used with a bit of creativity. For example, take a look at how you can change the columns count dynamically:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import {TextView, CollectionView, Slider, contentView} from 'tabris'; const items = createItems(); contentView.append( <$> <CollectionView stretchX top bottom='next()' columnCount={3} cellHeight={128} itemCount={items.length} createCell={createCell} updateCell={updateCell}/> <Slider left={16} bottom={0} right='next()' height={48} minimum={1} maximum={8} selection={3} onSelectionChanged={updateColumnCount}/> <TextView id='label' bottom={16} right={24} width={24} font='bold 14px' alignment='right' text='3'/> </$> ); function createCell() { return new TextView({ font: {size: 32, weight: 'bold'}, textColor: '#555555', alignment: 'centerX', maxLines: 1 }); } /** * @param {TextView} cell * @param {number} index */ function updateCell(cell, index) { cell.text = `${items[index]}`; cell.background = index % 2 === 0 ? '#cfd8dc' : '#ffffff'; } function updateColumnCount() { const columnCount = $(Slider).only().selection; $(CollectionView).only().columnCount = columnCount; $('#label').only(TextView).text = `${columnCount}`; } function createItems() { const result = []; for (let i = 1; i <= 100; i++) { result.push(i); } return result; } |
Use the CollectionView documentation page to find out more about the widget properties and methods.
Feedback is welcome!
Want to join the discussion?Feel free to contribute!