Skip to main content

CollectionView Overview

CollectionView

CollectionView is Hosanna's large-list surface. It virtualizes rows and cells, recycles view instances, and keeps focus state stable while data changes. Use it for rails, grids, tabbed rows, EPG-style rows, and any list that can grow or load dynamically.

Use ScrollView for small static groups of real views. Use CollectionView when data drives rows and cells, when items can be appended or removed, or when you need recycling and row-level layout behavior.

CollectionView row and cell layout model

A CollectionView renders visible rows, each row positions its cells, and focus is tracked by row and item index.

Quick Start

Collections Collectionview Basic

@view('CollectionsCollectionviewBasic')
export class CollectionsCollectionviewBasicView extends BaseExampleScreenView<CollectionsCollectionviewBasicState> {
  @state private dataSource = new CollectionViewDataSource([]);

  constructor() {
    super();
    // Seed a couple of rows using the built-in 'rows.regular' style
    const rows: ICollectionViewDataSourceRow[] = [
      this.createRow('Row A', 6),
      this.createRow('Row B', 8),
    ];
    this.dataSource.appendRows(rows, undefined, true);
  }

  protected getViews(): ViewStruct<ViewState>[] {
    // --- edit below ---

    return [
      VGroup([
        Label({ text: 'CollectionView: Basic' }),
        Button({ text: 'Add Row', width: 300 })
          .isInitialFocus(true)
          .onClick(() => this.dataSource.appendRows([this.createRow('New Row', 5)], undefined, true)),
        CollectionView({ id: 'cv' })
          .translation([0, 80])
          .dataSource(this.dataSource),
      ]).itemSpacing(12)
    ];

    // --- edit above ---
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private createRow(label: string, count = 6): ICollectionViewDataSourceRow<any, any> {
    const items = Array(count).fill(0).map((_, i) => ({
      id: `${label}-item-${i + 1}`,
      imageSet: { $RES$: 'https://via.assets.so/movie.png?w=384&h=216&q=85' },
    }));
    return {
      id: `row-${label}-${Math.random().toString(36).slice(2, 7)}`,
      settingsKey: 'rows.regular',
      data: { label },
      items,
    };
  }
}

Core Model

  • View: CollectionView({ id }).dataSource(dataSource) renders the current CollectionViewDataSource.
  • Rows: each data source row has an id, settingsKey, optional settingsOverrides, optional row data, and an items array.
  • Settings: row and cell styles live in assets/meta/app.config.json under top-level rows and cells.
  • Cells: most rows use DynamicCell, which renders fragment JSON and applies normal, focused, selected, and disabled state styles.
  • Focus: focusedIndices stores [rowIndex, itemIndex]; events expose row and item indices, and helper methods return focused row/item data.

AppConfig Row and Cell Styles

Rows are configured by style keys such as rows.regular. settingsOverrides can adjust an individual row without creating a new global style.

{
"rows": {
"regular": {
"rowType": "HorizontalRow",
"height": 317,
"contentOffset": [255, 0],
"cellSize": [384, 216],
"spacing": 15,
"screenPosition": [0, 150],
"cellSettingsKey": "cells.regular",
"headerSettings": {
"height": 51,
"labelOffset": [255, 0],
"fontKey": "~theme.fonts.heading-24"
},
"focusSettings": {
"indicatorImageUri": "images/input-focusrect.9.png",
"indicatorAppearance": "onTop"
}
}
}
}

Cells use fragment-style config. $supportsDataMap enables ${data.*} bindings; $RES$ inside a data path is replaced with the active resolution suffix.

{
"cells": {
"regular": {
"$supportsDataMap": true,
"views": {
"base": [
{
"id": "poster",
"subType": "Poster",
"width": 384,
"height": 216,
"uri": "${data.imageSet.$RES$}"
}
],
"normal": {
"poster": { "loadingBitmapUri": "~theme.images.placeholder" }
},
"focused": {
"poster": { "scale": [1.05, 1.05] }
}
}
}
}
}

API Surface

  • CollectionView: dataSource, rowSpacing, focusIndicatorAppearance, onItemSelected, onItemLongPressSelected, onOptionsKeyPressed, onItemFocus, onRowFocus.
  • Navigation helpers: jumpToRow(rowIndex, itemIndex?, force?), scrollToRow(rowIndex, itemIndex?, force?), renderForIndices(rowIndex, itemIndex).
  • Focused data helpers: getFocusedDataSourceRow(), getFocusedDataSourceItem(), getDataSourceItemForIndex(rowIndex, itemIndex), getCellForIndex(rowIndex, itemIndex).
  • DataSource: appendRows, replaceAllRows, appendItemsToRow, removeItemsFromRow, updateItem, removeRow, moveRowToIndex, changeRowEnabled, ChangeRowHidden, applyUpdates.
  • Pointer support: mouse hover/click, wheel scrolling, touch drag, horizontal row axis locking, momentum, and pointer focus indicator modes are handled by the web input adapters.

Learn More

  • CollectionView API: API
  • Styles and AppConfig: guide
  • Web Expression, DPI, and Touch Input: guide