Collection views
UICollectionView controls
The UICollectionView
is a key view type in UIKit and Apple’s Human Interface Guidelines. The Fiori Design Language utilizes collection views in a number of floorplans, especially Object Details, Overview, as well as in the Gallery View, Object CollectionView and Attachments section of the Create View.
The SAPFiori utilizes UICollectionView
instances in a number of controls, and when the content for those controls should be managed by the developer, it typically exposes the collection view as a public property in the API. A developer should use the regular UIKit API’s to configure and populate the item views of the collection, and handle things like taps and transitions.
The SAPFiori controls exposing a collection view property include:
FUITableViewCollectionSection
with embeddedFUICollectionViewTableViewCell
FUIAttachmentsController
These controls implement some context-specific behavior for the collection view–usually around layout and sizing–but when starting to implement a custom collection case, the starting point for a developer should be to work directly with *UICollectionView
***.
Then, the developer can use one or more of the UICollectionViewLayout
types from the SAPFiori framework to govern the item layout, and/or choose from the available UICollectionViewCell
subclasses in the framework to match the design specification.
UICollectionViewLayout
subclasses
FUICollectionViewLayout.horizontalScroll
The .horizontalScroll
layout extends UICollectionViewFlowLayout
. This layout should be used when the user should pan horizontally in the collection view, to view items off-screen to the left or right. Items in a section extend in a single row to infinity, so items will not wrap to new lines.
A developer should set the itemSize
property of the layout, to specify the standard dimensions of the cell items. Or, the developer may implement the UICollectionViewDelegateFlowLayout
, to specify unique sizes for each cell item.
A developer may optionally return views to the UICollectionViewDataSource
collectionView(_:viewForSupplementaryElementOfKind:at:)
method, to set ‘supplementary’ views to the collection view’s section header or footer. Multiple sections are supported, though cells in all sections will scroll simultaneously, so single section collections are most common.
Important: this layout ignores the
estimatedItemSize
property, even if assigned.
FUICollectionViewLayout.horizontalFlow
The .horizontalFlow
layout extends UICollectionViewFlowLayout
, by adding a new optional property: minimumScaledItemSize
, which enables the collection view cell items’ dimensions to be scaled upwards, to fill the width of the collection view’s contentSize
.
The developer may allow the layout to scale any number of cell items to fit the contentSize
width, or, may set a pre-determined number of items which ought to fit the contentSize
width, by setting the numberOfColumns
property. This is useful, when the number of items rendered in the collection view vary on different screens, but a common size is desired.
The .horizontalFlow
layout also controls the inter-item spacing, and line spacing, so that the minimumInteritemSpacing
and minimumLineSpacing
values provided by the developer are used precisely, rather than being adjusted by the AutoLayout engine.
With the introduction of this new size property, the UICollectionViewFlowLayout
item size is managed by the following priority:
- Autolayout system, if
estimatedItemSize
is set not equal toCGSize.zero
FUICollectionViewHorizontalFlowLayout
, withnumberOfColumns
property, ifminimumScaledItemSize
is set not equal toCGSize.zero
FUICollectionViewHorizontalFlowLayout
, ifminimumScaledItemSize
is set not equal toCGSize.zero
itemSize
property (Note:collectionView(_:layout:sizeForItemAt:)
value is ignored)
Default flow layout behavior
Flow layout behavior, using minimumScaledItemSize
FUICollectionViewLayout.autosizingColumnFlow
The autosizingColumnFlow
resizes collection view cell items, to lay them out according to a specified number of columns. All items per row are top-aligned, though the cell item height may vary, based upon the AutoLayout system’s height calculation for the cell. The leading/trailing edges of the first and last columns abut the respective margins of the content view.
The developer may specify the number of columns, by setting the numberOfColumns
property.
Collection view cell items supplied to the UICollectionViewDataSource.collectionView(_:cellForItemAt:)
method for collection views utilizing this flow layout, should be well-prepared for the AutoLayout engine to calculate content sizes–especially heights.
### FUICollectionViewLayout.keyValueColumnFlow
The keyValueColumnFlow
is a variant of the autosizingColumnFlow
, with pre-configured layout characteristics for rendering collections of FUIKeyValueCollectionViewCell
items.
- minimumInteritemSpacing is set to 80.
- minimumLineSpacing is set to 24.
- sectionInset is set to UIEdgeInsetsMake(0, 8, 0, 8).
-
The
FUITableViewCollectionSection
control is designed to be used, when a section in aUITableView
should be dedicated to displaying aUICollectionView
, and, the height of that section should adjust to fit its contents.The collection section produces a single
FUICollectionViewTableViewCell
, which refreshes its height, after its subviewFUICollectionView
calculates the sizes of its subviewUICollectionViewCell
items.A developer uses the
FUITableViewCollectionSection
, by assigning a data source (/and delegate) to itscollectionView: FUICollectionView
property; then, he or she should supply itscollectionViewTableViewCell
property to aUITableViewDataSource.tableView(_:cellForRowAt:)
implementation.Important
A developer should retain a strong reference to aFUITableViewCollectionSection
.## Usage
See morelet workorders: [WorkOrder] = [WorkOrder]() override public func viewDidLoad() { let workOrdersLayout = FUICollectionViewLayout.horizontalFlow workOrdersLayout.itemSize = CGSize(width: 200, height: 200) self.workOrdersSection = FUITableViewCollectionSection(tableView: self.tableView, collectionViewLayout: workOrdersLayout) self.workOrdersSection.collectionView.dataSource = self self.workOrdersSection.collectionView.register(FUISimpleCollectionViewCell.self, forCellWithReuseIdentifier: FUISimpleCollectionViewCell.reuseIdentifier) self.workOrdersSection.collectionView.delegate = self self.workOrdersSection.collectionView.isScrollEnabled = false self.tableView.estimatedRowHeight = 98 self.tableView.rowHeight = UITableViewAutomaticDimension } // MARK: UITableViewDataSource override public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return self.workOrdersSection.collectionViewTableViewCell } // MARK: UICollectionViewDataSource public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { switch collectionView { case workOrdersSection.collectionView: let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FUISimpleCollectionViewCell.reuseIdentifier, for: indexPath) as! FUISimpleCollectionViewCell cell.contentImageView.image = UIImage(named: "WorkOrderImage") cell.titleLabel.text = "Work Order: \(indexPath.item)" return cell default: // ... } }
Declaration
Swift
open class FUITableViewCollectionSection
-
UITableViewCell
subclass, containing a full-framecollectionView: FUIResizingCollectionView
. TheFUICollectionViewTableViewCell
should be returned by theFUITableViewCollectionSection
collectionViewTableViewCell
property.Important
The resizing behavior of theFUIResizingCollectionView
is dependent upon the internal size change handler. By default, thecollectionView
size will be controlled by itsintrinsicContentSize
. Developers should size theFUICollectionViewTableViewCell
accordingly.Declaration
Swift
open class FUICollectionViewTableViewCell: NibDesignableTableViewCell
-
FUISimpleCollectionViewCell is a variant of
UICollectionViewCell
defined inSAPFiori
. It contains aUIImageView
and aUILabel
.Code usage:
Implement collectionView(_:cellForItemAt:) dataSource method
//Implement collectionView(_:cellForItemAt:) dataSource method func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FUISimpleCollectionViewCell.reuseIdentifier, for: indexPath) as! FUISimpleCollectionViewCell //configure cell cell.contentImage = UIImage() cell.titleText = "Title" return cell }
Create and assign a layout object to collection view
See morelet layout = UICollectionViewFlowLayout() // Set any custom layout here. layout.itemSize = CGSize(width: 126, height: 126) layout.minimumInteritemSpacing = 10 layout.minimumLineSpacing = 10 // Sets the flow layout to CollectionView collectionView.collectionViewLayout = layout collectionView.dataSource = self collectionView.register(FUISimpleCollectionViewCell.self, forCellWithReuseIdentifier: FUISimpleCollectionViewCell.reuseIdentifier)
Declaration
Swift
open class FUISimpleCollectionViewCell: NibDesignableCollectionViewCell
-
A variant of
UICollectionViewCell
which is very similar toSimplePropertyFormCell
except that it’s not editable.keyName
: The key of the cell.value
: The value of the cell.
Code usage:
Register
FUISimplePropertyCollectionViewCell
for a collection view object.swift self.collectionView.register(FUISimplePropertyCollectionViewCell.self, forCellWithReuseIdentifier: FUISimplePropertyCollectionViewCell.reuseIdentifier)
Dequeue a
FUISimplePropertyCollectionViewCell
object from a collection view’s dataSource methodcollectionView(_:cellForItemAt:)
“`swift public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: FUISimplePropertyCollectionViewCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyCollectionViewCellswitch indexPath.item { case 0: cell.keyName = "Name" cell.value = "Broken Plates on Pole" case 1: cell.keyName = "Sort No." cell.value = "0001" default: break } return cell
} ”`
See moreDeclaration
Swift
public class FUISimplePropertyCollectionViewCell: NibDesignableCollectionViewCell
-
FUIKeyValueCollectionViewCell is a variant of
UICollectionViewCell
defined inSAPFiori
. It contains aUILabel
and aUITextField
.Code usage:
Register
FUIKeyValueCollectionViewCell
for a collection view object.self.collectionView.register(FUIKeyValueCollectionViewCell.self, forCellWithReuseIdentifier: FUIKeyValueCollectionViewCell.reuseIdentifier)
Implement collection view’s dataSource method
collectionView(_:cellForItemAt:)
See morepublic func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: FUIKeyValueCollectionViewCell.reuseIdentifier, for: indexPath) as! FUIKeyValueCollectionViewCell switch indexPath.item { case 0: cell.keyName = "Name" cell.value = "Broken Plates on Pole" case 1: cell.keyName = "Sort No." cell.value = "0001" default: break } return cell }
Declaration
Swift
public class FUIKeyValueCollectionViewCell: NibDesignableCollectionViewCell
-
Set of
See moreUICollectionViewFlowLayout
s occurring in Fiori Design Language.Declaration
Swift
public enum FUICollectionViewLayout
-
This layout extends
UICollectionViewFlowLayout
, by adding a new optional property:minimumScaledItemSize
, which enables the collection view cell items’ dimensions to be scaled upwards, to fill the width of the collection view’scontentSize
.The developer may allow the layout to scale any number of cell items to fit the
contentSize
width, or, may set a pre-determined number of items which ought to fit thecontentSize
width, by setting thenumberOfColumns
property. This is useful, when the number of items rendered in the collection view vary on different screens, but a common size is desired.This layout also controls the inter-item spacing, and line spacing, so that the
minimumInteritemSpacing
andminimumLineSpacing
values provided by the developer are used precisely, rather than being adjusted by the AutoLayout engine.Code usage
Assign an instance of FUIHorizontalScrollCollectionViewLayout to your collection view.
swfit self.collectionView.collectionViewLayout = FUICollectionViewLayout.horizontalScroll
Implement collectionView(:cellForItemAt:) dataSource. “`swfit public func collectionView( collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FUIObjectCollectionViewCell.reuseIdentifier, for: indexPath) as! FUIObjectCollectionViewCell //You may use any type of collection view cell here. //configue cell here //… return cell } ”`
Implement following methods if you need section header/footer. You can also set headerReferenceHeight/footerReferenceHeight to apply same height for all headers/footers. “`swift func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier:
Header
, for: indexPath) as! FUICollectionSectionHeaderFooterView //configue header/footer view here //… return view }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { switch section { case 0: return CGSize(width: 40, height: 40) default: return CGSize(width: 60, height: 60) }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { switch section { case 0: return CGSize(width: 40, height: 40) default: return CGSize(width: 60, height: 60) } ”`
See moreDeclaration
Swift
open class FUIHorizontalFlowCollectionViewLayout: UICollectionViewFlowLayout
-
This layout should be used when the user should pan horizontally in the collection view, to view items off-screen to the left or right. Items in a section extend in a single row to infinity, so items will not wrap to new lines.
A developer should set the
itemSize
property of the layout, to specify the standard dimensions of the cell items.Code usage
Assign an instance of FUIHorizontalScrollCollectionViewLayout to your collection view.
swfit self.collectionView.collectionViewLayout = FUICollectionViewLayout.horizontalScroll
Implement collectionView(:cellForItemAt:) dataSource. “`swfit public func collectionView( collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FUIObjectCollectionViewCell.reuseIdentifier, for: indexPath) as! FUIObjectCollectionViewCell //You may use any type of collection view cell here. //configue cell here //… return cell } ”`
Implement following methods if you need section header/footer. You can also set headerReferenceHeight/footerReferenceHeight to apply same height for all headers/footers. “`swift func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier:
Header
, for: indexPath) as! FUICollectionSectionHeaderFooterView //configue header/footer view here //… return view }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { switch section { case 0: return CGSize(width: 40, height: 40) default: return CGSize(width: 60, height: 60) }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { switch section { case 0: return CGSize(width: 40, height: 40) default: return CGSize(width: 60, height: 60) } ”`
See moreDeclaration
Swift
open class FUIHorizontalScrollCollectionViewLayout: UICollectionViewFlowLayout
-
The
FUIStandardAutoSizingColumnFlowLayout
resizes collection view cell items, to lay them out according to a specified number of columns. All items per row are top-aligned, though the cell item height may vary, based upon the AutoLayout system’s height calculation for the cell.Code usage
Assign an instance of FUIStandardAutoSizingColumnFlowLayout to your collection view.
swfit self.collectionView.collectionViewLayout = FUICollectionViewLayout.autosizingColumnFlow
Implement collectionView(:cellForItemAt:) dataSource. “`swfit public func collectionView( collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FUIObjectCollectionViewCell.reuseIdentifier, for: indexPath) as! FUIObjectCollectionViewCell //configue cell here //… return cell } ”`
Implement following methods if you need section header/footer. You can also set headerReferenceHeight/footerReferenceHeight to apply same height for all headers/footers. “`swift func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier:
Header
, for: indexPath) as! FUICollectionSectionHeaderFooterView //configue header/footer view here //… return view } }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { switch section { case 0: return CGSize(width: 40, height: 40) default: return CGSize(width: 60, height: 60) }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { switch section { case 0: return CGSize(width: 40, height: 40) default: return CGSize(width: 60, height: 60) } ”`
See moreDeclaration
Swift
open class FUIStandardAutoSizingColumnFlowLayout: UICollectionViewLayout
-
A subclass of
FUIStandardAutoSizingColumnFlowLayout
which resizes collection view cell items, to lay them out according to a specified number of columns. All items per row are top-aligned, though the cell item height may vary, based upon the AutoLayout system’s height calculation for the cell.minimumInteritemSpacing
is set to 80 andminimumLineSpacing
is set to 24 by default.sectionInset
is set to ‘top: 0, left: 8, bottom: 0, right: 8’.Declaration
Swift
public class FUIKeyValueFlowLayout: FUIStandardAutoSizingColumnFlowLayout
-
UICollectionView subclass, which invokes a
sizeChangeHandler: (() -> Void)?
closure, when the current content size of the collection does not match the intrinsic content size. The sizeChangeHandler property isinternal
to the SDK.Developers should generally not initialize
FUIResizingCollectionView
directly. Instead, instances of the class are typically accessed through theFUITableViewCollectionSection
API’s.Important
Resizing behavior will only be executed, if thesizeChangeHandler
is implemented.Declaration
Swift
public class FUIResizingCollectionView: UICollectionView