Hierarchy View
-
A view controller which specializes in managing a hierarchy view. When
FUIHierarchyViewController
initiates, it sets data source and delegate of hierarchy view to self.Components
hierarchyView
Usage
Subclass
FUIHierarchyViewController
when you need to show a hierarchy view. It conforms toFUIHierarchyViewDataSource
andFUIHierarchyViewDelegate
by default.class MyController: FUIHierarchyViewController {}
Override
viewDidLoad
and do some setup here. You should register your custom cell if needed. Otherwise hierarchy view will useFUIHierarchyCollectionItem
by default.override func viewDidLoad() { super.viewDidLoad() hierarchyView.register(YourCustomCollectionViewCell.self, forCellWithReuseIdentifier: "ReuseIdentifierForYourCustomCell") // do more setup here. }
Implement
dataSource
and delegate methods// Define your data model. var model = HierarchyViewModel() override func rootUUID(in hierarchyView: FUIHierarchyView) -> String? { return model.rootObject?.uuid } override func hierarchyView(_ hierarchyView: FUIHierarchyView, numberOfChildrenForItemWith uuid: String) -> Int { guard let object = model.getObject(for: uuid) else { preconditionFailure("Object with String: \(uuid) does not exsit in model") } if let children = object.children { return children.count } // Get children asynchronously if they haven't been loaded yet. When loading completes, cache those children for future access and insert children into hierarchy view by calling `insertChildren(of:at:)`. object.asyncFetchChildren { children in self.model.updateCache(objects: children) self.hierarchyView.insertChildren(of: uuid, at: IndexSet(integersIn: 0..<children.count)) } // Return zero children before children is loaded. return 0 } override func hierarchyView(_ hierarchyView: FUIHierarchyView, uuidForChildItemAt index: Int, with parentUUID: String) -> String { guard let parent = model.getObject(for: parentUUID) else { preconditionFailure("Parent object with String: \(parentUUID) does not exsit") } guard let children = parent.children else { preconditionFailure("Children of parent: \(parent) is not loaded yet") } return children[index].uuid } override func hierarchyView(_ hierarchyView: FUIHierarchyView, parentForItemWith uuid: String) -> String? { guard let object = model.getObject(for: uuid) else { preconditionFailure("Object with String: \(uuid) does not exsit in model") } if let parent = object.parent { return parent.uuid } // Get parent asynchronously if they haven't been loaded yet. When loading completes, cache the parent for future access and insert it into hierarchy view by calling `invalidateParent(of:)`. object.asyncFetchParent { parent in guard let parent = parent else { return } self.model.updateCache(objects: [parent]) self.model.updateRootObject(newRootObject: parent) self.hierarchyView.invalidateParent(of: uuid) } // Return nil before parent is loaded. return nil } override func hierarchyView(_ hierarchyView: FUIHierarchyView, cellForItemWith uuid: String) -> FUIHierarchyCollectionItem { let cell = hierarchyView.dequeueReusableCell(withReuseIdentifier: “ReuseIdentifierForYourCustomCell”, with: uuid) as! YourCustomCollectionViewCell guard let object = model.getObject(for: uuid) else { return cell } cell.title.text = object.name cell.subtitle.text = object.type cell.body.text = object.location cell.accessoryType = .disclosureIndicator if object.numberOfChildren > 0 { cell.isHierarchyButtonHidden = false cell.hierarchyAttributeText = String(object.numberOfChildren) } else { cell.isHierarchyButtonHidden = true } return cell } override func hierarchyView(_ hierarchyView: FUIHierarchyView, titleForItemWith uuid: String) -> String? { return model.getObject(for: uuid)?.name }
Theming
Supported class paths:
See morefdlHierarchyViewController_hierarchyView {}
Declaration
Swift
open class FUIHierarchyViewController : UIViewController, FUIHierarchyViewDataSource, FUIHierarchyViewDelegate
-
A view that manages a collection of items in a multi-column layout.
Initial Loading Process:
- Hierarchy view asks data source for a root item and put it in the first column. Hierarchy view will be empty if
nil
is returned for root. If so, hierarchy view finishes loading. - Hierarchy view asks data source for number of children of the root and get each child item iteratively.
- Hierarchy view asks data source for the parent of root item. If that parent exists, insert it into preview column before the root.
Interaction Behavior:
Expand Children
Tap on the hierarchy accessory view will drill down one level in the hierarchy view to show the children of tapped item.
Swipe
Quick swipe left/right to view the previous or next level in the hierarchy.
Pan
Pan left/right to navigate further in hierarchy view.
Usage
Have your data source object conform to
FUIHierarchyViewDataSource
protocol and set it to hierarchy view’sdataSource
property.class YourHierarchyViewDataSource: FUIHierarchyViewDataSource {} hierarchyView.dataSource = YourHierarchyViewDataSource()
Register your custom cell if needed. Otherwise hierarchy view will use
FUIHierarchyCollectionItem
by default.hierarchyView.register(YourCustomCollectionViewCell.self, forCellWithReuseIdentifier: "ReuseIdentifierForYourCustomCell")
Implement
dataSource
methods.// Define your data model. var model = HierarchyViewModel() func rootUUID(in hierarchyView: FUIHierarchyView) -> String? { return model.rootObject?.uuid } func hierarchyView(_ hierarchyView: FUIHierarchyView, numberOfChildrenForItemWith uuid: String) -> Int { guard let object = model.getObject(for: uuid) else { preconditionFailure("Object with String: \(uuid) does not exsit in model") } if let children = object.children { return children.count } // Get children asynchroniously if they haven't been loaded yet. When loading completes, cache those children for future access and insert children into hierarchy view by calling `insertChildren(of:at:)`. object.asyncFetchChildren { children in self.model.updateCache(objects: children) self.hierarchyView.insertChildren(of: uuid, at: IndexSet(integersIn: 0..<children.count)) } // Return zero children before children is loaded. return 0 } func hierarchyView(_ hierarchyView: FUIHierarchyView, uuidForChildItemAt index: Int, with parentUUID: String) -> String { guard let parent = model.getObject(for: parentUUID) else { preconditionFailure("Parent object with String: \(parentUUID) does not exsit") } guard let children = parent.children else { preconditionFailure("Children of parent: \(parent) is not loaded yet") } return children[index].uuid } func hierarchyView(_ hierarchyView: FUIHierarchyView, parentForItemWith uuid: String) -> String? { guard let object = model.getObject(for: uuid) else { preconditionFailure("Object with String: \(uuid) does not exsit in model") } if let parent = object.parent { return parent.uuid } // Get parent asynchronously if they haven't been loaded yet. When loading completes, cache the parent for future access and insert it into hierarchy view by calling `invalidateParent(of:)`. object.asyncFetchParent { parent in guard let parent = parent else { return } self.model.updateCache(objects: [parent]) self.model.updateRootObject(newRootObject: parent) self.hierarchyView.invalidateParent(of: uuid) } // Return nil before parent is loaded. return nil } func hierarchyView(_ hierarchyView: FUIHierarchyView, cellForItemWith uuid: String) -> FUIHierarchyCollectionItem { let cell = hierarchyView.dequeueReusableCell(withReuseIdentifier: “ReuseIdentifierForYourCustomCell”, with: uuid) as! YourCustomCollectionViewCell guard let object = model.getObject(for: uuid) else { return cell } cell.title.text = object.name cell.subtitle.text = object.type cell.body.text = object.location cell.accessoryType = .disclosureIndicator if object.numberOfChildren > 0 { cell.isHierarchyButtonHidden = false cell.hierarchyAttributeText = String(object.numberOfChildren) } else { cell.isHierarchyButtonHidden = true } return cell } func hierarchyView(_ hierarchyView: FUIHierarchyView, titleForItemWith uuid: String) -> String? { return model.getObject(for: uuid)?.name }
Make your delegate object conform to
FUIHierarchyViewDelegate
protocol and assign it to hierarchy view’s delegate property if needed.class YourHierarchyViewDelegate: FUIHierarchyViewDelegate {} hierarchyView.delegate = YourHierarchyViewDelegate()
Theming
Supported class paths:
See morefdlFUIHierarchyView {} fdlFUIHierarchyView_header {}
Declaration
Swift
open class FUIHierarchyView : UIView, FUIContentCopyable
- Hierarchy view asks data source for a root item and put it in the first column. Hierarchy view will be empty if
-
A concrete layout class that manages the layout of hierarchy view.
This layout organizes items into different columns from left to right (right to left if in opposite layout direction) where items in one column happens to be the children of expanded item in the previous column. This layout is specially designed for hierarchy view so it is supposed to be used along with hierarchy view.
See moreDeclaration
Swift
open class FUIHierarchyCollectionViewLayout : UICollectionViewLayout, UIScrollViewDelegate
-
The FUIHierarchyViewDelegate protocol defines methods that allow you to manage the selection of items or tapping on hierarchy accessory view of collection item cell in a hierarchy view. The methods of this protocol are all optional.
See moreDeclaration
Swift
@objc public protocol FUIHierarchyViewDelegate
-
An object that adopts the UICollectionViewDataSource protocol is responsible for providing the data required by a hierarchy view. It also handles the creation and configuration of cells used by the hierarchy view to display your data.
See moreDeclaration
Swift
public protocol FUIHierarchyViewDataSource : AnyObject
-
FUIHierarchyItemTableViewCell
is a table view UI component which extendsFUIObjectBaseTableViewCell
for showing a collection item’s business object content and hierarchy information (e.g. number of children in its next level). It is identical toFUIHierarchyCollectionItem
in terms of the configuration of inner view and hierarchy indicator.Initialization and Configuration:
To use
FUIHierarchyItemTableViewCell
, it should be dequeued fromhierarchyView
and returned in the data source method inFUIHierarchyViewDataSource
.Example of setting an
FUIHierarchyCollectionItem
in a table view:cell.title.text = "Business Object Title" cell.subtitle.text = "Business Object Subtitle" cell.footnote.text = "Business Object Footnote" cell.hierarchyIndicator.title.text = "128" cell.status.text = "Business Object Status" cell.accessoryType = .disclosureIndicator
Settings of Hierarchy Indicator:
Similar to
FUIHierarchyCollectionItem
, hierarchy indicator is used to display related hierarchy information. To customize a different text in hierarchy indicator, set thetext
fortitle
property of the cell’sFUIHierarchyIndicator
.cell.hierarchyIndicator.title.text = "My Title"
Likewise, hierarchy indicator by default is displayed in a vertical aligned multi-line mode in
FUIHierarchyCollectionItem
. To display in single-line mode, configure theisMultiline
property of the cell’sFUIHierarchyIndicator
.cell.hierarchyIndicator.isMultiline = false
Layout of Hierarchy Indicator in Table View:
The default width of the space showing hierarchy indicator is
38px
in multi-line mode and74px
in multi-line mode. So the table view controller consuming theFUIHierarchyItemTableViewCell
should enforce this minimum layout margin based on its display mode. The recommended technique for managing this is to set the table view controller’sadditionalSafeAreaInsets
property accordingly.override func viewDidLoad() { self.tableView.showsVerticalScrollIndicator = false self.tableView.insetsContentViewsToSafeArea = false if UIView.userInterfaceLayoutDirection(for: self.view.semanticContentAttribute) == .leftToRight { self.additionalSafeAreaInsets.right = 38 } else { self.additionalSafeAreaInsets.left = 38 } }
Default Styling:
Depending on the selection state, the tint color and button style of hierarchy icon, the font size of the title text, and the cell’s background color will be updated automatically.
Customize Selection Behavior:
Similar to
FUIHierarchyCollectionItem
, selection behavior can be customized by conforming toFUIHierarchyViewDelegate
and then implementing thehierarchyButtonTappedForItemWith
method.AccessoryView
,AccessoryType
, andEditingAccessoryView
Standard
UITableViewCell
properties likeaccessoryView
,accessoryType
, andeditingAccessoryView
are supported.Theming
Supported class paths:
fdlFUIBaseCollectionViewCell {} fdlFUIBaseCollectionViewCell_title {} fdlFUIBaseCollectionViewCell_subtitle {} fdlFUIBaseCollectionViewCell_footnote {} fdlFUIBaseCollectionViewCell_detailImageView {}
Please refer to
See moreFUIHierarchyItemView
andFUIHierarchyIndicator
documentation for all supported attributes.Declaration
Swift
open class FUIHierarchyItemTableViewCell : FUIObjectBaseTableViewCell<FUIHierarchyItemView>
-
A header view sits at top of hierarchy view. Header label displays the title of the selected parent item in previous section. You can use left/right button to navigate back or forth in the hierarchy.
Theming
Supported class paths:
fdlFUIHierarchyViewHeader {} fdlFUIHierarchyViewHeader_title {} fdlFUIHierarchyViewHeader_leftButton {} fdlFUIHierarchyViewHeader_rightButton {}
Please refer to
See moreFUIButton
documentation for all supported attributes.Declaration
Swift
open class FUIHierarchyViewHeader : UIView, FUIViewBorderDrawing
-
Base inner view showing business object information for
FUIHierarchyItemTableViewCell
andFUIHierarchyCollectionItem
.Example Initialization and Configuration:
let view = FUIHierarchyItemView() view.title.text = "Business Object Title" view.subtitle.text = "Business Object Subtitle" view.footnote.text = "Business Object Footnote" view.status.text = "Business Object Status" view.statusImageView.image = UIImage(named: <#image#>) view.iconImages = ["1", FUIIconLibrary.indicator.veryHighPriority.withRenderingMode(.alwaysTemplate)]
Theming
Supported
TEXT
class paths:fdlFUIHierarchyItemView_title {} fdlFUIHierarchyItemView_subtitle {} fdlFUIHierarchyItemView_footnote {} fdlFUIHierarchyItemView_status {}
Supported
TEXT
properties:font-color: Color; font-style: UIFontTextStyle; text-align: NSTextAlignment;
Supported
IMAGE
class paths:fdlFUIHierarchyItemView_detailImageView {}
Supported
IMAGE
properties:
See moretint-color: Color;
Declaration
Swift
open class FUIHierarchyItemView : FUIObjectViewBase, FUIHierarchyItemComponent
-
FUIHierarchyCollectionItem
is a collection view UI component which extendsFUITableViewAccessoryDrawingCollectionViewCell
for showing a collection item’s business object content and hierarchy information (e.g. number of children in its next level). It is the default cell for displaying hierarchy items in anFUIHierarchyView
.Initialization and Configuration:
To use
FUIHierarchyCollectionItem
, it should be dequeued fromhierarchyView
and returned in the data source method inFUIHierarchyViewDataSource
.Example of setting an
FUIHierarchyCollectionItem
by implementingcellForItemWith
in the hierarchy view:cell.title.text = "Business Object Title" cell.subtitle.text = "Business Object Subtitle" cell.footnote.text = "Business Object Footnote" cell.accessoryType = .disclosureIndicator cell.statusImage = FUIIconLibrary.indicator.veryHighPriority cell.hierarchyIndicator.title.text = "999,999"
Hierarchy Indicator:
Hierarchy indicator provides a stacked view which includes two components: a text view, and a hierarchy icon. In hierarchy view, the text view is used to show the number of children belongs to the specific hierarchy item. Once the hierarchy indicator is tapped, the hierarchy view will be expanded to display a list of its children in a new column. The icon indicates that if the hierarchy item has been expanded or not. To customize a different text in hierarchy indicator, set the
text
fortitle
property of the cell’sFUIHierarchyIndicator
.cell.hierarchyIndicator.title.text = "My Title"
Hierarchy indicator has two ways to layout its components: multi-line mode and single-line mode. By default, it is displayed in a vertical aligned multi-line mode. To horizontally align its components in a single-line mode, configure the
isMultiline
property of the cell’sFUIHierarchyIndicator
.cell.hierarchyIndicator.isMultiline = false
Default Styling:
Depending on the selection state, the tint color and button style of hierarchy icon, the font size of the title text, and the cell’s background color will be updated automatically.
Customize Selection Behavior:
By default after selection the hierarchy item cell will be expanded. Selection behavior can be customized by conforming to
FUIHierarchyViewDelegate
and then implementing thehierarchyButtonTappedForItemWith
method. To support additional gesture handling, a developer would usually add a gesture recognizer. This can be added directly to the cell when it is being dequeued, or added to collection view containing the cell.In the following example, a long press gesture recognizer is added to each hierarchy collection cell:
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(didLongPress(_:))) longPressGestureRecognizer.minimumPressDuration = 0.5 cell.addGestureRecognizer(longPressGestureRecognizer)
Theming:
Supported class paths:
fdlFUIHierarchyCollectionItem {}
Please refer to
See moreFUIHierarchyItemView
andFUIHierarchyIndicator
documentation for all supported attributes.Declaration
Swift
open class FUIHierarchyCollectionItem : FUITableViewAccessoryDrawingCollectionViewCell<FUIHierarchyItemView>, InnerViewContainerEventHandling, FUIContentCopyable
-
See moreFUIHierarchyState
is an hierarchy object that defines its selection state: normal or selected.Declaration
Swift
public struct FUIHierarchyState : Hashable
extension FUIHierarchyState: Enableable
extension FUIHierarchyState: Defaultable
-
Hierarchy indicator is a stack view including a hierarchy icon and the specific item’s hierarchy title text view, which is used by
FUIHierarchyItemTableViewCell
andFUIHierarchyCollectionItem
.Theming
Supported class paths:
fdlFUIHierarchyIndicator_title {}
Supported
TEXT
properties:font-color: Color; font-style: UIFontTextStyle; text-align: NSTextAlignment;
See moreDeclaration
Swift
open class FUIHierarchyIndicator : FUITintableDrawingView<FUIHierarchyState>, FUITitleComponent