TTMSFMXNativeUICollectionView
Usage
The TMSFMXNativeUICollectionView
class manages an ordered collection of data items and presents them using customizable layouts. Collection views provide the same general function as table views except that a collection view is able to support more than just single-column layouts.
With this implementation, the visual representation is based on a template, which is available for the header, footer and the item. The TMSFMXNativeUICollectionView
component comes with a designer that allows creating and modifying these templates. Each template allows adding various controls such as a label, image, button, stepper, etc... The template control is stored and accessible separately as a non-visual component.
Methods
Methods name | Description |
---|---|
AddFooterTemplateButton | A set of overloads that adds a button template control to the Footer template. |
AddFooterTemplateCheckBox | A set of overloads that adds a checkbox template control to the Footer template. |
AddFooterTemplateControl | A set of overloads that allows adding a template control the the footer template. Additional properties need to be set to the template control result or parameter depending on the type of overload that is chosen. |
AddFooterTemplateImageView | A set of overloads that adds an imageview template control to the Footer template. |
AddFooterTemplateLabel | A set of overloads that adds a label template control to the Footer template. |
AddFooterTemplateProgressView | A set of overloads that adds a progressview template control to the Footer template. |
AddFooterTemplateStepper | A set of overloads that adds a stepper template control to the Footer template. |
AddFooterTemplateSwitch | A set of overloads that adds a switch template control to the Footer template. |
AddFooterTemplateTextField | A set of overloads that adds a textfield template control to the Footer template. |
AddFooterTemplateTextView | A set of overloads that adds a textview template control to the Footer template. |
AddHeaderTemplateButton | A set of overloads that adds a button template control to the Header template. |
AddHeaderTemplateCheckBox | A set of overloads that adds a checkbox template control to the Header template. |
AddHeaderTemplateControl | A set of overloads that allows adding a template control to the header template. Additional properties need to be set to the template control result or parameter depending on the type of overload that is chosen. |
AddHeaderTemplateImageView | A set of overloads that adds an imageview template control to the Header template. |
AddHeaderTemplateLabel | A set of overloads that adds a label template control to the Header template. |
AddHeaderTemplateStepper | A set of overloads that adds a stepper template control to the Header template. |
AddHeaderTemplateSwitch | A set of overloads that adds a switch template control to the Header template. |
AddHeaderTemplateTextField | A set of overloads that adds a textfield template control to the Header template. |
AddHeaderTemplateTextView | A set of overloads that adds a textview template control to the Header template. |
AddItemTemplateButton | A set of overloads that adds a button template control to the item template. |
AddItemTemplateCheckBox | A set of overloads that adds a checkbox template control to the item template. |
AddItemTemplateControl | A set of overloads that allows adding a template control to the item template. Additional properties need to be set to the template control result or parameter depending on the type of overload that is chosen. |
AddItemTemplateImageView | A set of overloads that adds an imageview template control to the item template. |
AddItemTemplateLabel | A set of overloads that adds a label template control to the item template. |
AddItemTemplateProgressView | A set of overloads that adds a progressview template control to the item template. |
AddItemTemplateStepper | A set of overloads that adds a stepper template control to the item template. |
AddItemTemplateSwitch | A set of overloads that adds a switch template control to the item template. |
AddItemTemplateTextField | A set of overloads that adds a textfield template control to the item template. |
AddItemTemplateTextView | A set of overloads that adds a textview template control to the item template. |
DeselectItem / DeselectItems / DeselectAllItems | Deselects a specific or multiple item(s) identified with a section and row parameter. |
GetFooterTemplateControl | Returns a footer template control with a specific section, row and id parameter. |
GetHeaderTemplateControl | Returns a header template control with a specific section, row and id parameter. |
GetItemTemplateControl | Returns an item template control with a specific section, row and id parameter. |
ReloadData | Reloads the complete CollectionView, discarding and re-initializing items, headers and footers. |
ReloadItem / ReloadItems | Visually update a single or an array of TCollectionViewItem with a section and row parameter. |
ReloadSection / ReloadSections | Visually update a single or an array of Integer with a section parameter. Each reload of a section will also reload all items that the section holds. |
ScrollToItem | Scrolls to a specific item with a section and row parameter. Optionally allows passing the scrollposition and whether scrolling needs to be performed with or without animation. |
SelectedItems | Returns an array of selected items. |
SelectItem / SelectItems / SelectAllItems | Selects and scrolls to a specific or multiple item(s) identified with a section and row parameter. Optionally allows passing the scrollposition and whether scrolling needs to be performed with or without animation. |
VisibleItems | Returns an array of visible items. |
Public Events
Important note
Events that might require additional iOSApi units and have native iOS parameters, use only when the published events do not suffice
Events name | Description |
---|---|
OnAddItemBackground | Event called when the default background view is added, allowing for more customization. |
OnAddItemSelectedBackground | Event called when the default selected background view is added, allow for more customization. |
Event called to allow more customization on the footer view after the template controls values are applied. | |
OnApplyHeaderValues | Event called to allow more customization on the Header view after the template controls values are applied. |
OnApplyItemBackground | Event called to allow more customization on the background view. This event differs with the OnAddItemBackground in a way that it is called when an item is being re-used instead of initialized. When the background remains static and does not change when scrolling, interacting with the items. The OnAddItemBackground event needs to be used, else the OnApplyItemBackground . |
OnApplyItemSelectedBackground | Event called to allow more customization on the selected background view. This event differs with the OnAddItemSelectedBackground in a way that it is called when an item is being re-used instead of initialized. When the selected background remains static and does not change when scrolling, interacting with the items. The OnAddItemSelectedBackground event needs to be used, else the OnApplyItemSelectedBackground . |
OnApplyItemValues | Event called to allow more customization on the item view after the template controls values are applied. |
OnInitializeFooterTemplate | Event called to allow more customization on the footer view after the template controls are created and added to the footer. This event is only called when the footer is created. Use this event if the changes you have made afterwards remain static else use the OnApplyFooterValues event. |
OnInitializeHeaderTemplate | Event called to allow more customization on the header view after the template controls are created and added to the header. This event is only called when the header is created. Use this event if the changes you have made afterwards remain static else use the OnApplyHeaderValues event. |
OnInitializeItemBackground | Event called with a native iOS UIView parameter that represents the item view and optionally allows creating an item background view that is used to apply the Options.ItemBackgroundColor property. Setting the ACreate parameter to false allows you to create your own native background view. |
OnInitializeItemSelectedBackground | Event called with a native iOS UIView parameter that represents the item view and optionally allows creating an item selected background view that is used to apply the Options.ItemSelectedBackgroundColor property. Setting the ACreate parameter to false allows you to create your own native selected background view. |
OnInitializeItemTemplate | Event called to allow more customization on the item view after the template controls are created and added to the item. This event is only called when the item is created. Use this event if the changes you have made afterwards remain static, else use the OnApplyItemValues event. |
Published Events
The most important events are listed below, events such as an OnItemButtonClick
, OnItemStepperValueChanged
and equivalents for Header
and Footer
are not listed. These events depend on the kind of template that is constructed and used at runtime.The CollectionView is implemented with a virtual mode and requires some of the events that are listed below (marked in red).
Events name | Description |
---|---|
OnGetItemBackgroundColor | Event called to retrieve the background color of an item. |
OnGetItemSelectedBackgroundColor | Event called to retrieve the background color of an item used in selected state. |
OnGetInsetForSectionAtIndex | Event called to retrieve the inset for a section at a specific index. |
OnGetMinimumInteritemSpacingForSectionAtIndex | Event called to retrieve the minimum spacing between items on the same line in a section. |
OnGetMinimumLineSpacingForSectionAtIndex | Event called to retrieve the minimum spacing between lines in a section. |
OnGetReferenceSizeForFooterInSection | Event called to retrieve the reference size of the footer in a specific section. |
OnGetReferenceSizeForHeaderInSection | Event called to retrieve the reference size of the header in a specific section. |
OnGetSizeForItemAtIndexPath | Event called to retrieve the size for an item at a specific section and row. |
OnDidSelectItem | Event called when an item is selected. |
OnDidDeselectItem | Event called when an item is deselected. |
OnShouldSelectItem | Event called before an item will be selected. You can use this event to prevent selection of specific items. |
OnShouldDeselectItem | Event called before an item will be deselected. You can use this event to prevent deselection of specific items. |
OnGetNumberOfSections | Event called to retrieve the number of sections in the ColectionView. When this method is not implemented, the CollectionView returns 1 section by default. |
OnGetNumberOfItemsInSection | Event called to retrieve the number of items in the CollectionView. When this method is not implemented, the CollectionView returns 5 items per section by default. |
OnAddHeaderControl | Event called when a header template control is initialized. Implement this event to set properties on a specific template control that remains static during the usage of the CollectionView. |
OnAddFooterControl | Event called when a footer template control is initialized. Implement this event to set properties on a specific template control that remains static during the usage of the CollectionView. |
OnAddItemControl | Event called when an item template control is initialized. Implement this event to set properties on a specific template control that remains static during the usage of the CollectionView. |
OnApplyHeaderValue | Event called when a header template control will apply its values. Implement this event to set properties on a specific template control that is dynamic and changes it values depending on section parameter. |
OnApplyFooterValue | Event called when a footer template control will apply its values. Implement this event to set properties on a specific template control that is dynamic and changes it values depending on the section parameter. |
OnApplyItemValue | Event called when an item template control will apply its values. Implement this event to set properties on a specific template control that is dynamic and changes it values depending on the section and row parameter. |
Templates
The CollectionView core is based on templates. Each section in the CollectionView consists of a header, footer and a number of items (elements). During creation, these elements are initialized and reused where possible, the CollectionView reads the controls inside the template, creates them and triggers a set of events (explained in the table of public and published events) that can be used to assign a value to a specific control inside an element based on the section and row parameter.
For header and footers, the row parameter will always be 0
.
On CollectionView level, the template used to visualize an element is stored inside a generic list of TTMSFMXNativeUICollectionViewTemplateControl
. This class has a number of descendants that define a native iOS control that can be used inside an element.
First Initialization
Before the CollectionView will start displaying sections, with optional header and footer, the CollectionView needs 2
events implemented. The first one is the OnGetNumberOfSections
which returns 1
by default, if the event is not implemented. The second one is the OnGetNumberOfItemsInSection
which returns 5
by default and needs to be mapped to the number of items / sections in your data structure. Afterwards, you can start adding template controls to visualize your data per item and / or section. In the code sample below, we add 2
sections, and respectively 5
and 3
items.
procedure TForm1.TMSFMXNativeUICollectionView1GetNumberOfItemsInSection(
Sender: TObject; ASection: Integer; var ANumberOfItems: Integer);
Begin
if ASection = 0 then
ANumberOfItems := 5
else
ANumberOfItems := 3;
end;
procedure TForm1.TMSFMXNativeUICollectionView1GetNumberOfSections(
Sender: TObject; var ANumberOfSections: Integer);
begin
ANumberOfSections := 2;
end;
Adding template controls
Programmatically adding a control to the template of an element can be done with on of the various functions that are listed in the table above. Each element has its own template and thus its own set of functions. For an item the function starts with “AddItemTemplate”
, for a header and footer respectively “AddHeaderTemplate”
and “AddFooterTemplate”
. The second part is based on the type of template control you wish to add to the element. Below is a sample of adding a label to the item template.
procedure TForm1.FormCreate(Sender: TObject);
var
lbl: TTMSFMXNativeUICollectionViewTemplateLabel;
begin
lbl := TMSFMXNativeUICollectionView1.AddItemTemplateLabel(10, 10, 100, 25, 'Hello World !');
end;
Template
property on CollectionView level. As explained in the previous chapter, the CollectionView then loads and initializes the header, footer and item elements and loops through the template collection of each element. In this sample, a native iOS UILabel
will be added to the item.
Initializing / modifying values
After defining the template for either the header, footer and / or the item, the CollectionView initializes the elements and creates a native iOS control for each template control. The CollectionView manages each element separately in memory and reuses its elements where possible.
The CollectionView does not manage a separate data structure, so the data that needs to be visualized will need to be passed by implementing some events. The “First Initialization”
chapter already mentioned events to determine how many sections and items are going to be displayed. Next, after adding template controls to the header, footer and / or item with optionally default values, the data can be mapped on the control by implementing 2
events. These events are also called per element which means that we have an equivalent for the header, footer and item. In this sample code, we continue with our label template control that we have programmatically added.
The code shows how to define a default font, font size and text color that will be applied to all items.
procedure TForm1.FormCreate(Sender: TObject);
var
lbl: TTMSFMXNativeUICollectionViewTemplateLabel;
begin
lbl := TMSFMXNativeUICollectionView1.AddItemTemplateLabel(10, 10, 100, 25, 'Hello World !');
lbl.Font.Name := 'Helvetica Bold';
lbl.Font.Size := 18;
lbl.TextColor := TAlphaColorRec.Red;
end;
Running the application will show a CollectionView with 5
items per section, with red bold text and the default value “Hello World” that is set in the FormCreate
.
As explained, each label has the same color, font and text based on the template control of the item element. To modify these default values dynamically, we will need to implement an event that manages this. The OnApplyItemValue
event is called with a section and row parameter and allows you to modify the value of the item. There are also equivalents for the header and footer that will be demonstrated after adding a template control to the header as well.
The code below shows how to access the label with a special helper function that is available in the FMX.TMSNativeUICollectionView
unit to detect if the template control is a Label
control. Each control inherits from the base control and is passed as a parameter of this event.
procedure TForm1.TMSFMXNativeUICollectionView1ApplyItemValue(Sender: TObject;
AControl: TTMSFMXNativeUICollectionViewTemplateControl; ASection,
ARow: Integer);
begin
if IsLabel(AControl) then
AsLabel(AControl).Text := 'Item ' + inttostr(ASection) + ':' + inttostr(ARow);
end;
Now, the header is visible as well, but does not show a template control, so we can use the same approach as like we did with the item, and add a control to the header template and modify its value afterwards through the appropriate event. The same could be done for the footer, but then you would need to set the FooterVisible
property to true which is located under the Options
property. The complete code for this sample can be found below:
procedure TForm1.FormCreate(Sender: TObject);
var
lbl: TTMSFMXNativeUICollectionViewTemplateLabel;
begin
lbl := TMSFMXNativeUICollectionView1.AddItemTemplateLabel(10, 10, 100, 25, 'Hello World !');
lbl.Font.Name := 'Helvetica Bold';
lbl.Font.Size := 18;
lbl.TextColor := TAlphaColorRec.Red;
lbl := TMSFMXNativeUICollectionView1.AddHeaderTemplateLabel(10, 10, 100, 25, '');
lbl.Font.Name := 'Helvetica Bold';
lbl.Font.Size := 22;
lbl.TextColor := TAlphaColorRec.Blue;
end;
procedure TForm1.TMSFMXNativeUICollectionView1ApplyHeaderValue(
Sender: TObject; AControl: TTMSFMXNativeUICollectionViewTemplateControl;
ASection, ARow: Integer);
begin
if IsLabel(AControl) then
AsLabel(AControl).Text := 'Section ' + inttostr(ASection);
end;
procedure TForm1.TMSFMXNativeUICollectionView1ApplyItemValue(Sender: TObject;
AControl: TTMSFMXNativeUICollectionViewTemplateControl; ASection,
ARow: Integer);
begin
if IsLabel(AControl) then
AsLabel(AControl).Text := 'Item ' + inttostr(ASection) + ':' + inttostr(ARow);
end;
procedure TForm1.TMSFMXNativeUICollectionView1GetNumberOfItemsInSection(
Sender: TObject; ASection: Integer; var ANumberOfItems: Integer);
begin
if ASection = 0 then
ANumberOfItems := 5
else
ANumberOfItems := 3;
end;
procedure TForm1.TMSFMXNativeUICollectionView1GetNumberOfSections(
Sender: TObject; var ANumberOfSections: Integer);
begin
ANumberOfSections := 2;
end;
Identifiers
In the sample above, we have added one label to the header and one to the item template. By default each template control is uniquely identified by its index. If you wish to add an additional template label to the item, the identifier is incremented and accessible in the order that they are added to the template. The identifier starts from 1
for the first item. The code of the OnApplyItemValue
modified with a “description label” could then be implemented like the sample below:
procedure TForm1.TMSFMXNativeUICollectionView1ApplyItemValue(Sender: TObject;
AControl: TTMSFMXNativeUICollectionViewTemplateControl; ASection,
ARow: Integer);
begin
if IsLabel(AControl) and (AControl.GetViewID = 1) then
AsLabel(AControl).Text := 'Title ' + inttostr(ASection) + ':' + inttostr(ARow);
if IsLabel(AControl) and (AControl.GetViewID = 2) then
AsLabel(AControl).Text := 'Description ' + inttostr(ASection) + ':' + inttostr(ARow);
end;
If you have a special template control that needs to be accessible in an easy way, you can specify an ID to your template control. The ID
property needs to be 1
or higher and is returned by the GetViewID
function to identify the correct control. If you have multiple template controls of the same type and want to manage them with an easier accessibility, this is the way to identify them.
Interaction
The CollectionView supports a variety of template controls such as a label, imageview, progressview but also interactable controls such as a button. Adding a button is done in the same way as adding a label, can optionally and uniquely be identified and is also accessible to modify its values dynamically.
The CollectionView exposes events that are triggered when clicking a button, editing text in a textview or toggling the switch,with a section and row parameter.
Designtime editor
Programmatically adding, modifying and positioning controls can be useful to quickly have a rough idea on how your application would possibly look like. You can then concentrate on the data structure, implement interaction, selection, database handling, etc…. and handle the visualization afterwards. It might also be sufficient if you only have a label and an image and they are positioned without indenting, under eachother with the image taking up the remaining space after substracting the label height from the item height, but this will be easier said than done in some cases.
To cover the “easier said than done” part, we have created a designtime template editor that acts as a helper to create a template for the header, footer and / or item element. Under the Template
property on CollectionView level you will notice three templates. Click on the three dots next to the template of choice to start the editor.
The editor will display a dotted rectangle that represents the boundaries of the element depending on the chosen template. On the left you can add template controls, position them relatively inside the element rectangle. A newly created template control is accessible as a non-visual component both at designtime and at runtime. It can also be removed as easily as it has been added. Below is the template of the item element shown inside the editor, and the result after the application is started and the data is loaded.
Performance
The CollectionView manages a state where it checks if a property is modified, sets a flag and updates the appropriate properties on the template control in one of the OnApply*Value
events, but each control that is added to the template is passed as a parameter to this event so you can manipulate the data and visual aspects. When having multiple controls that remain identical for each element during the lifetime of the CollectionView, such as image shadows, text, buttons it is unnecessary to call the OnApply*Value
event for these template controls. This will affect performance in a positive way and will allow you to manage the controls that really matter for your application.
When adding a new template control, you will notice a State
property that is being set to csDynamic
by default. In the demo you will notice by selecting the shadow item template control that the State
property is being set to csStatic
as the shadow is identical for each item.