Create and Filter patterns
The FormKit API includes a set of UITableViewCells that should be used in the Fiori Design Language to construct table views for creating or editing business objects, or to build filter controls. Each cell implements the FUIFormCell protocol and invokes an optional onChangeHandler closure to handle value changes.
FormKit cells are used in Filter and Create Floorplans.

Interface
All cells in FormKit implement the FUIFormCell protocol. FUIFormCell is generic for its value property, and has an associatedtype: ValueType, that allows the value to be accessed with type safety.
FUITitleFormCell - displays the title of the form. The cell can be marked as editable to allow user editing of the title (for example, the “Work Request” cell in the above image):
let cell = tableView.dequeueReusableCell(withIdentifier: FUITitleFormCell.reuseIdentifier, for: indexPath) as! FUITitleFormCell
cell.value = "Work Request"
cell.isEditable = false
return cell
FUINoteFormCell - the user can enter notes in the cell (for example, the cell between “Work Request” and “Request ID” in the above image):
let cell = tableView.dequeueReusableCell(withIdentifier: FUINoteFormCell.reuseIdentifier, for: indexPath) as! FUINoteFormCell
cell.placeholder.text = "Description"
cell.value = self.noteText
cell.onChangeHandler = { [unowned self] newValue in
self.noteText = newValue
}
return cell
FUIKeyValueFormCell - the user can enter text in the cell:

let cell = tableView.dequeueReusableCell(withIdentifier: FUIKeyValueFormCell.reuseIdentifier, for: indexPath) as! FUIKeyValueFormCell
cell.keyName = "Note"
cell.placeholder.text = "Description"
cell.value = myObject.descriptionText1
cell.isTrackingLiveChanges = true
cell.isEditable = false
cell.onChangeHandler = { [unowned myObject] newValue in
myObject.descriptionText1 = newValue
}
return cell
FUIFilterFormCell - allow users to select one or multiple values from a value set:

let cell = tableView.dequeueReusableCell(withIdentifier: FUIFilterFormCell.reuseIdentifier, for: indexPath) as! FUIFilterFormCell
cell.valueOptions = buttonTitles.flatMap { $0.map { $0.value }}
cell.keyName = "Sort By"
cell.value = self.selectedValue
cell.allowsMultipleSelection = true
cell.allowsEmptySelection = false
cell.onChangeHandler = { [unowned self] newValue in
self.selectedValue = newValue
}
return cell
FUIListPickerFormCell - provides a key/value pair that displays the key and value of the cell. For single selection, set its allowsMultipleSelection property to false:

var selectedValue: [Int] = [0]
// A property cell with list picker
let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell
cell.keyName = "Work Group"
cell.value = selectedValue
cell.valueOptions = ["Construction", "Repair", "Engineering", "Vendor"]
cell.allowsMultipleSelection = false
cell.valueLabel.text = descriptionForSelectedStrings(cell.valueOptions, at: selectedValue)
cell.onChangeHandler = { [unowned self] newValue in
self.selectedValue = newValue
}
return cell
When this cell is selected, a table view displays the available options for the user to choose:

A FUIListPickerFormCell can also be set as multiple selectable in the app by setting its allowsMultipleSelection property to true, as follows in the UITableViewController:

let valueOptions12 = ["One", "Two", "Three", "Four", "Five", "Six", "Seven"]
var propValue12 = [1, 3, 6]
//...
// A property cell with list picker
let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell
cell.keyName = "Choose Multiple"
cell.value = propValue12
cell.valueOptions = valueOptions12
// Developer is responsible for setting the text for the valueTextField of the FUIListPickerFormCell.
// Here, function descriptionForSelectedStrings just returns the
// comma separated selected string.
cell.valueLabel.text = descriptionForSelectedStrings(valueOptions12, at: propValue12)
cell.allowsMultipleSelection = true
cell.listPicker.prompt = "Please select multiple items"
cell.onChangeHandler = { [unowned self] newValue in
self.propValue12 = newValue
}
return cell

When the cell is tapped, a multiple select table with specified optional values is displayed:

A developer could customize the cells displayed in the selection table by setting the dataSource property of the listPicker property of the FUIListPickerFormCell, as described below:
let propKey11 = "List Picker with Object Cells"
var propValue11: [Int] = []
// ObjectCellListPickerDataSource implements ListPickerDataSource and ListPickerSearchResultsUpdating
let listPickerDataSource11 = ObjectCellListPickerDataSource(40)
// ...
// A FUIListPickerFormCell with FUIObjectTableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell
cell.keyName = propKey11
cell.value = propValue11
cell.valueLabel.text = listPickerDataSource11.descriptionForSelectedItems(at: propValue11)
cell.listPicker.dataSource = listPickerDataSource11
cell.listPicker.searchResultsUpdating = listPickerDataSource11
cell.listPicker.prompt = "Please select multiple items"
cell.listPicker.register(FUIObjectTableViewCell.self, forCellReuseIdentifier: FUIObjectTableViewCell.reuseIdentifier)
cell.allowsMultipleSelection = true
cell.allowsEmptySelection = true
cell.onChangeHandler = { [unowned self] newValue in
self.propValue11 = newValue
}
return cell
When the cell is tapped, a multiple select table with FUIObjectTableViewCell is displayed:

A search bar could be added to the FUIListPickerFormCell in the selection table view by setting isSearchEnabled, dataSource and listPickerResultsUpdating. Optionally, a barcode scanner could be added to the search bar by setting the isBarcodeScannerEnabled property of the searchBar property, as follows:
let propKey7 = "Choose Multiple"
var propValue7: [Int] = []
let listPickerDataSource7 = StringListPickerDataSource(options: ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"])
// ...
let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell
cell.keyName = propKey7
cell.value = propValue7
cell.allowsMultipleSelection = true
cell.allowsEmptySelection = false
cell.valueLabel.text = descriptionForSelectedStrings(cell.valueOptions, at: propValue7)
cell.listPicker.dataSource = listPickerDataSource7
cell.listPicker.searchResultsUpdating = listPickerDataSource7
cell.listPicker.prompt = "Please select multiple items"
cell.listPicker.isSearchEnabled = true
cell.onChangeHandler = { [unowned self] newValue in
self.propValue7 = newValue
}
cell.listPicker.searchBar?.isBarcodeScannerEnabled = true
cell.listPicker.searchBar?.barcodeScanner?.scanMode = .EAN_UPC
cell.listPicker.searchBar?.barcodeScanner?.scanResultTransformer = { (scanString) -> String in
return self.transformStringToSearchBar(scanResultString: scanString)
}
return cell

When the cell is tapped, the multiple selection table is shown with a search bar under the navigation bar.

When the user starts typing in the search bar, the displayed list is filtered.

When the barcode scanner icon is tapped, the barcode scan view is displayed. Note that the barcode scanner icon is not displayed when the device does not support a camera, for example, when it’s running on a simulator. Also, the icon is not displayed when the search bar is active.

FUIDatePickerFormCell - provides a key/value pair that displays a key and a date as the property value. When this cell is selected, a UIDatePicker displays to allow the user to select a date. The app can provide a DateFormatter to customize how the date displays:

var propValue4: Date = Date()
// ...
let cell = tableView.dequeueReusableCell(withIdentifier: FUIDatePickerFormCell.reuseIdentifier, for: indexPath) as! FUIDatePickerFormCell
cell.key = "Appointment Date"
cell.value = propValue4
cell.onChangeHandler = { [unowned self] newValue in
self.propValue4 = newValue
}
return cell
FUIDurationPickerFormCell - provides a key/value pair that displays a key and a TimeInterval as the property value. When this cell is selected, a UIDatePicker displays to allow the user to select a duration. The app can provide a text formatter to customize how the duration displays (for example, the formatter by default is “%d Hrs %d Min”):

var propValue10: TimeInterval = 3900
// ...
let cell = tableView.dequeueReusableCell(withIdentifier: FUIDurationPickerFormCell.reuseIdentifier, for: indexPath) as! FUIDurationPickerFormCell
cell.keyName = "Duration"
cell.value = propValue10
cell.onChangeHandler = { [unowned self] newValue in
self.propValue10 = newValue
}
return cell
FUIValuePickerFormCell - provides a key/value pair that displays a key and a String as the property value. When this cell is selected, a UIPickerView displays to allow the user to select a value:

let priceTitles = [[5: "5"], [10: "10"], [15: "15"], [20: "20"], [25: "25"]]
// ...
let cell = tableView.dequeueReusableCell(withIdentifier: FUIValuePickerFormCell.reuseIdentifier, for: indexPath) as! FUIValuePickerFormCell
cell.keyName = "Maximum Price"
cell.valueOptions = priceTitles.compactMap { $0.first?.value }
cell.value = priceTitles.index { $0.first!.key == self.myObject.price }!
// MARK: implement an `onChangeHandler`
cell.onChangeHandler = { [unowned self] newValue in
self.myObject.price = self.priceTitles[newValue].first!.key
}
return cell
FUISwitchFormCell - the property for this cell is a boolean value that uses a standard UISwitch to display the value. The user can change the value by tapping the switch:

var isConfirmed = false
// ...
// A FUISwitchFormCell
let cell = tableView.dequeueReusableCell(withIdentifier: FUISwitchFormCell.reuseIdentifier, for: indexPath) as! FUISwitchFormCell
cell.key = "Confirmed"
cell.value = isConfirmed
cell.onChangeHandler = { [unowned self] newValue in
self.isConfirmed = newValue
}
return cell
FUISliderFormCell - the property for this cell is a float value. Users select a value from a continuous range using the slider. Also set a unit if needed (default unit is “mi”):

let cell = tableView.dequeueReusableCell(withIdentifier: FUISliderFormCell.reuseIdentifier, for: indexPath) as! FUISliderFormCell
cell.keyName = "Distance"
cell.minimumValue = 0
cell.maximumValue = 30
cell.value = myObject.distance
// MARK: implement an `onChangeHandler`
cell.onChangeHandler = { newValue in
self.myObject.distance = newValue
}
return cell
FUIAttachmentFormCell - a cell to which photos or selected files can be added as attachments:
let cell = tableView.dequeueReusableCell(withIdentifier: FUIAttachmentsFormCell.reuseIdentifier, for: indexPath) as! FUIAttachmentsFormCell
cell.attachmentsController.delegate = self
cell.attachmentsController.dataSource = self
cell.attachmentsController.reloadData()
cell.attachmentsController.maxItems = 8
return cell
The application needs to add the following to its info.plist in order to access the camera and photo library:
<key>NSCameraUsageDescription</key>
<string>Please permit access to camera</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Please permit access to photo library</string>
Each UITableViewController is allowed to have only one FUIAttachmentFormCell.
FUISegmentedControlFormCell - A type of FUIPropertyFormCell, representing a key/value pair of the cell. The user can select a value by clicking the button. The cell is editable by default and can be set to isEditable to disable user interaction.

var selectedItemIndex = 1
// ...
let cell = tableView.dequeueReusableCell(withIdentifier: FUISegmentedControlFormCell.reuseIdentifier, for: indexPath) as! FUISegmentedControlFormCell
cell.valueOptions = ["Low", "Medium", "High"]
cell.keyName = "Key"
cell.value = selectedItemIndex
cell.onChangeHandler = { [unowned self] newValue in
self.selectedItemIndex = newValue
}
return cell
Usage
Implement a UITableViewController that hosts the cells and constructs a Create Window view similar to the one in the example above:
The UITableViewController must subclass FUIFormTableViewController.
class MyFormTableViewController: FormTableViewController {
...
}
Register the reuse identifiers of all needed FUIFormCells, and enable auto-dimension row height calculation.
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(FUITitleFormCell.self, forCellReuseIdentifier: FUITitleFormCell.reuseIdentifier)
...
self.tableView.estimatedRowHeight = 200
self.tableView.rowHeight = UITableViewAutomaticDimension
}
Reuse the registered cells in tableView(_:cellForRowAt:), and bind the form data to the cell views:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// An simple key-value property cell
let cell = tableView.dequeueReusableCell(withIdentifier: FUISimplePropertyFormCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyFormCell
cell.key = "Location"
cell.value = "127 Higgins Drive, Palo Alto"
// MARK: Implement `onChangeHandler` closure to process the new value entered by the user
cell.onChangeHandler = { newValue in
myObject.value = newValue
}
return cell
}
-
This protocol is to be implemented by all the form cells except
FUIAttachmentsFormCell, including:- FUIDatePickerFormCell
- FUIDurationPickerFormCell
- FUIFilterFormCell
- FUIKeyValueFormCell
- FUIListPickerFormCell
- FUINoteFormCell
- FUISegmentedControlFormCell
- FUISimplePropertyFormCell
- FUISliderFormCell
- FUIValuePickerFormCell
- FUISwitchFormCell
FUITitleFormCell
See moreNote
All
FUIFormCellimplementations listed above have theselectionStyleproperties set to.none. Therefore, developers will not be able to set highlighted on these cells.Declaration
Swift
public protocol FUIFormCell : AnyObject, FUIInlineValidation -
When
FUIFormCells are to be used in an application, application’s implementation ofUITableViewControllerthat hosts theseFUIFormCells must be a subclass of thisFUIFormTableViewController.FUIFormTableViewControllerhides all the complications and interactions for handling all different types ofFUIFormCells.Application’s implementation of the
UITableViewControllerneeds to only implement the following functions:class FormCellTestTVC: FUIFormTableViewController { override func viewDidLoad() { // MUST: Call viewDidLoad function of super class. super.viewDidLoad() // Register FUIFormCells that will be used self.tableView.register(FUITitleFormCell.self, forCellReuseIdentifier: FUITitleFormCell.reuseIdentifier) ... } override func numberOfSections(in tableView: UITableView) -> Int { // Return how many section in the table return ... } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // Return number of rows in each section ... } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Return the cell to be used at the IndexPath specified let cell = tableView.dequeueReusableCell(withIdentifier: FUITitleFormCell.reuseIdentifier, for: indexPath) as! FUITitleFormCell cell.value = "Work Request" cell.isEditable = true // MARK: implement onChangeHandler cell.onChangeHandler = { newValue in myObject.title = newValue } return cell }In addition, if there are some other actions on the table view, it is required that the action functions should also call function
endEditingof the table view with theforceparameter totrueso that all editing cells have its onChangeHandler called. For example, the function didSaveTapped below is the action when the “Save” button tapped:
See more@IBAction func didSaveTapped(_ sender: AnyObject) { self.tableView.endEditing(true) // save object ... }Declaration
Swift
@MainActor open class FUIFormTableViewController : UITableViewController, FUIFormCellResponderDelegate, FUIFormCellNavigationDelegate -
The reusable UI component implemented as an
UITableViewCellto allow user to enter a value, using aUITextField.
The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:value: The value of the property, asString
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value
Optionally, the developer may provide:
isEditable: Indicates if the cell’s value may be modified. Defaults totrue.
Color settings:
Setting tintColor for
valueTextFieldfor a state using setTintColor(_:for:) api. Currentlydisabledandnormalare supported.cell.setTintColor(UIColor.red, for: .normal)Remark
Thefont-colorattribute will be overridden bytint-color-disabledattribute when cell is switched todisabledstate. DO NOT settextColorforvalueTextFieldwhen cell is indisabledstate!The following is an example of usage in an application
UITableViewController:override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUITitleFormCell.self, forCellReuseIdentifier: FUITitleFormCell.reuseIdentifier) // ... } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUITitleFormCell.reuseIdentifier, for: indexPath) as! FUITitleFormCell cell.value = myObject.title cell.isEditable = true // MARK: implement onChangeHandler cell.onChangeHandler = { newValue in myObject.title = newValue } return cell }## Theming
Supported
TableViewCellclass paths:fdlFUITitleFormCell {}Supported
TableViewCellattributes:background-color (Color) background-color-disabled (Color) background-color-readonly (Color)Supported
TextFieldclass paths:fdlFUITitleFormCell_valueTextFieldSupported
TextFieldproperties:
See morefont-color: Color; font-color-disabled: Color; font-color-readonly: Color; placeholder-color: Color; font-style: UIFontTextStyle; font-style-disabled: UIFontTextStyle; font-style-readonly: UIFontTextStyle;Declaration
Swift
@MainActor open class FUITitleFormCell : FUIInlineValidationUIControlTintTableViewCell, FUIFormCell, UITextFieldDelegate, FUIStateReadOnly -
The reusable UI component implemented as an
UITableViewCellto display or edit a key-value pair property.The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the property.value: The value of the property.
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value
Optionally, the developer may provide
isEditable: Indicates if the cell’s value may be modified. Defaults totrue.isStacked: A boolean value to determine if the cell should use a stacked or linear layout. If the device’s accessibility settings font size is increased, the cell will force a stacked layout. By default, this property is set totrue.maxKeyWidth: The maximum width of the key with a linear layout - By default, the width is 115 for compact and 160 for regular. The set value must meet the minimum default threshold.alternativeInputButton: AnFUIButtonthat manages an alternative method to fill thetextField.isAlternativeInputEnabled: ABoolthat shows or hides thealternativeInputButton. This button will be displayed ifisAlternativeInputEnabledandisEditablearetrue.isReadOnly: Indicates if the cell is read-only or not. The default isfalse.isTrackingLiveChanges: Indicates if theonChangeHandlerwill be invoked for every letter entered. The default isfalse.isCharCountEnabled: A Boolean value to enable a character counter and show the updated character count number during editing. The default isfalse.maxTextLength: The maximum length of the text.allowsBeyondLimit: A Boolean value to determine whether the user can continue to input text even aftermaxValueTextLengthhas been reached. If it istrue, it will be in an error state with an error message and a semantic negative color when the text input exceedsmaxTextLength. The default isfalse.showsErrorInValidationMsg: A Boolean value to determine whether an error message will be shown in thevalidationMessageor in theerrorViewin the same layout as thehintView. The default istrue.hasError: A Boolean value to indicate if there is an error in the text input value. It will be in an error state with an error message and a semantic negative color if it istrue. The default isfalse.
Color settings:
Manage the color of the control by setting the
textColorandtintColorprogrammatically.The following is an example of usage in an application
UITableViewController:override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUITextFieldFormCell.self, forCellReuseIdentifier: FUITextFieldFormCell.reuseIdentifier) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUITextFieldFormCell.reuseIdentifier, for: indexPath) as! FUITextFieldFormCell cell.keyName = "Editable" cell.value = myObject.productName // MARK: implement onChangeHandler cell.onChangeHandler = { newValue in myObject.productName = newValue } // MARK: Implement alternative input, i.e. use OCR to capture input cell.isAlternativeInputEnabled = true let inputImage = FUIIconLibrary.system.camera cell.alternativeInputButton.setImage(inputImage.withRenderingMode(.alwaysTemplate), for: .normal) cell.alternativeInputButton.didSelectHandler = { [weak self, weak cell] (button) in //Import SAPML to use OCR capability let textRecController = FUITextRecognitionViewController() textRecController.recognitionView.observationHandler = { [unowned textRecController] observations in let filteredObservations = <#filter out unwanted text#> textRecController.recognitionView.showTexts(for: filteredObservations) let areObservationsValid = <#filteredObservations meets desired criteria#> if areObservationsValid { DispatchQueue.main.async { cell?.value = filteredObservations.map { $0.value }.joined(separator:" ") } return true } return false } textRecController.onClose = { self?.dismiss(animated: true) } self?.present(UINavigationController(rootViewController: textRecController), animated: true) } return cell }## Theming
nuiClass:fdlFUITextFieldFormCell {}Supported
TEXTclass paths:fdlFUITextFieldFormCell_keyText {} fdlFUITextFieldFormCell_valueText {}Supported
TEXTproperties:font-color: Color; placeholder-color: Color; font-style: UIFontTextStyle;Supported
BUTTONclass paths:fdlFUITextFieldFormCell_alternativeInputButton {}Supported
BUTTONproperties:
See morebackground-color: Color; font-color: Color;Declaration
Swift
@MainActor open class FUITextFieldFormCell : FUIInlineValidationDrawingTableViewCell<FUITextFieldContentView>, FUIFormCellextension FUITextFieldFormCell: FUITintAttributesProvider -
The reusable UI component implemented as an
UITableViewCellto allow user enter notes.
This is the new implementation to replace the previous implementation of
FUINoteFormCell. The cell height is automatically adjusted to allow the whole content to be displayed. However, the cell height is also limited to the height of the screen above the soft keyboard height.Developer could use to
UITableViewDelegate‘sfunc tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloatto set a fixed height for the cell. Or, useminNumberOfLinesandmaxNumberOfLinesproperties to limit the cell height.The character counter can be enabled by setting
isCharCountEnabled. It will show the updated the character count number during editing or has been entered. The message will be shown if themaxNoteTextLengthreached. The user can continue input the text ifallowsBeyondLimitistrue. It will show the text input field in error state with an error message and a semantic negative color. IfallowsBeyondLimitisfalse, it will auto-stop user input whenmaxNoteTextLengthis reached.The application can validate the user input value and show error message by setting
hasErroranderrorText. The text input field in error state with an error message and a semantic negative color. The error message can be shown in thevalidationMessageifshowsErrorInValidationMsgistrue. Otherwise, the error message will be shown in theerrorViewin the same layout as thehintView.Usage
let cell = tableView.dequeueReusableCell(withIdentifier: FUINoteFormCell.reuseIdentifier) as! FUINoteFormCell cell.onChangeHandler = { [unowned self] newValue in self.noteText = newValue } cell.placeholder.text = "Enter Description" cell.value = noteText cell.isTrackingLiveChanges = trueTheming
Supported
TEXTclass paths:fdlFUINoteFormCell_valueText {} fdlFUINoteFormCell_placeholder {}Supported
TEXTproperties:font-color: Color; font-style: UIFontTextStyle;Supported
TINTABLEclass paths:fdlFUIKeyValueFormCell_valueText {}Supported
TINTABLEproperties:
See moretint-color { -disabled }: Color; font-style { -disabled }: UIFontTextStyle;Declaration
Swift
@MainActor open class FUINoteFormCell : FUIAutofittingDrawingTableViewCell<FUINoteFormCellContentView>, FUIFormCell -
A customized
UITableViewCell, which contains aUILabeland aUITextView. It takes text as input.
This is a new implementation to replace the previous implementation of
FUIKeyValueFormCell. It has akeyNamefield and an editable value text field to let user entered the value for this property. This cell height is automatically adjusted to allow the whole content to be displayed. However, the cell height is also limited to the height of the screen above the soft keyboard height.Developer could use to
UITableViewDelegate‘sfunc tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloatto set a fixed height for the cell.The character counter can be enabled by setting
isCharCountEnabled. It will show the updated character count number during editing, or the number of characters that have been loaded from the back end. An error message will be shown if themaxNoteTextLengthis reached. It will also show the text input field in error state and a semantic negative color. The user can continue to input text ifallowsBeyondLimitistrue. IfallowsBeyondLimitisfalse, it will auto-stop user input whenmaxNoteTextLengthis reached.The application can validate the user input value and show an error message by setting
hasErroranderrorText. The text input field will be displayed in an error state with an error message and a semantic negative color. The error message can be shown in thevalidationMessageifshowsErrorInValidationMsgistrue. Otherwise, the error message will be shown in theerrorViewin the same layout as thehintView.Usage
let cell = tableView.dequeueReusableCell(withIdentifier: FUIKeyValueFormCell.reuseIdentifier) as! FUIKeyValueFormCell cell.onChangeHandler = { [unowned self] newValue in print("value: \(newValue)") self.value = newValue } cell.keyName = "Project Title" cell.placeholder.text = "Please enter a title" cell.value = value cell.isTrackingLiveChanges = true return cellTheming
Supported
TEXTclass paths:fdlFUIKeyValueFormCell_title {} fdlFUIKeyValueFormCell_valueText {} fdlFUIKeyValueFormCell_placeholder {} fdlFUIKeyValueFormCell_subtitle {}Supported
TEXTproperties:font-color: Color; font-style: UIFontTextStyle;Supported
TINTABLEclass paths:fdlFUIKeyValueFormCell_title {} fdlFUIKeyValueFormCell_valueText {}Supported
TINTABLEproperties:
See moretint-color { -disabled }: Color; font-style { -disabled }: UIFontTextStyle;Declaration
Swift
@MainActor open class FUIKeyValueFormCell : FUINoteFormCellextension FUIKeyValueFormCell: FUIPropertyFormCell -
The reusable UI component implemented as an
UITableViewCellto allow user to choose a boolean value using a switch for a property.
The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the propertyvalue: The value of the property, asBoolisEditable: Indicates if the cell’s value may be modified. Defaults totrue.
And, an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value
The following is an example of usage in an application
UITableViewController:override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUISwitchFormCell.self, forCellReuseIdentifier: FUISwitchFormCell.reuseIdentifier) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUISwitchFormCell.reuseIdentifier, for: indexPath) as! FUISwitchFormCell cell.keyName = "Confirmed" cell.value = myObject.isConfirmed cell.onChangeHandler = { newValue in myObject.isConfirmed = newValue } return cell }Theming
Supported style classes and attributes.
fdlFUISwitchFormCell { // Table view cell related attributes. // ... } fdlFUISwitchFormCell_title { // Font attributes font { -style | -name | -size } font-color // Number of lines text-line-clamp // Text alignment text-align } fdlFUISwitchFormCell_switch { tint-color // Knob color thumb-color { -enabled-selected | -enabled-unselected | -disabled-selected | -disabled-unselected } // Track color track-color { -enabled-selected | -enabled-unselected | -disabled-selected | -disabled-unselected } // Border color border-color { -enabled-selected | -enabled-unselected | -disabled-selected | -disabled-unselected } // View opacity view-alpha { -enabled-selected | -enabled-unselected | -disabled-selected | -disabled-unselected } }Note: As of iOS SDK 9.0, the version of
fdlFUISwitchFormCell_switchdescribed above is preferable to the version offdlFUISwitchFormCell_switchdescribed below (to achieve maximum UX design compliance).
See morefdlFUISwitchFormCell_switch { tint-color on-tint-color }Declaration
Swift
@MainActor open class FUISwitchFormCell : FUIInlineValidationDrawingTableViewCell<FUISwitchFormView> -
A customized
UITableViewCell, which contains aUILabel, aUITextFieldand aUISlider. It allows users to select a single value from a continuous range of values.
The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the propertyvalue: The value of the property, asFloatminimumValue: The minimum value of the selection range.maximumValue: The maximum value of the selection range.
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value.
Optionally, the developer may set:
unit: The unit of value. Default ismi.isEditable: Indicates if the cell’s value may be modified. Defaults totrue.
Color setting:
Setting text color of filter buttons for a state using setTintColor(_:for:) api. Currently
.disabledand.normalare supported.cell.setTintColor(UIColor.red, for: .normal)The following is an example of usage in an application
UITableViewController:override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUISliderFormCell, forCellReuseIdentifier: FUISliderFormCell.reuseIdentifier) // ... } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUISliderFormCell.reuseIdentifier, for: indexPath) as! FUISliderFormCell cell.keyName = "Distance" cell.minimumValue = 0 cell.maximumValue = 30 cell.value = myObject.distance // MARK: implement an onChangeHandler cell.onChangeHandler = { [weak self] newValue in self.myObject.distance = newValue } return cell }Theming
Supported style classes
See morefdlFUISliderFormCell fdlFUISliderFormCell_keyLabel fdlFUISliderFormCell_valueTextFieldDeclaration
Swift
@IBDesignable @MainActor open class FUISliderFormCell : FUIInlineValidationTableViewCell, FUIPropertyFormCell -
The reusable UI component implemented as a
UITableViewCell, allowing a user to select range values from the slider, which can be controlled using a single thumb or double thumbs.The developer should set the following properties on the cell in their implementation of the
UITableViewDataSourcecellForRow(at:)function:title: The key name of the property.minimumValue: The minimum value of the slider.maximumValue: The maximum value of the slider.- “
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value
Optionally, the developer may provide
isEditable: Indicates whether the cell’s value can be modified. The default istrue.lowerValue: The minimum value the user can select.upperValue: The maximum value the user can select.isRangeSelection: Determine the slider whether show one thumb or two thumbs. Default is true.subtitle: the hint text.interval: the minimum value of the slider as it changes. The default is1.isContinuous: whether value change events are generated any time. The default istrue.
The following is an example of usage in an application
UITableViewController:override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUIRangeSliderFormCell.self, forCellReuseIdentifier: FUIRangeSliderFormCell.reuseIdentifier) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUIRangeSliderFormCell.reuseIdentifier, for: indexPath) as! FUIRangeSliderFormCell cell.title = "Range Label" cell.maximumValue = 50 cell.minimumValue = 10 cell.subtitle = "Hint Text" cell.isEditable = true cell.upperValue = 40 cell.lowerValue = 20 cell.isRangeSelection = true // MARK: implement onChangeHandler cell.onChangeHandler = { (lower, upper) in // ... } return cell }## Theming
nuiClass:fdlFUIRangeSliderFormCell {}Supported
keyView:fdlFUIRangeSliderFormCell_keyText { font-color { -highlighted | -disabled } (Color) font-style { -highlighted | -disabled } (UIFont.TextStyle) }Supported
slider:fdlFUIRangeSliderFormCell_slider { track-tint-color { -disabled } (Color); track-selection-color { -disabled } (Color); thumb-tint-color { -disabled } (Color); }Supported
textfields:fdlFUIRangeSliderFormCell_textFields { font-color { -disabled } (Color) font-style { -disabled } (UIFont.TextStyle) border-color { -highlighted | -readonly } (Color) }Supported
hintText:
See morefdlFUIRangeSliderFormCell_hintText { font-color { -disabled } (Color) font-style { -disabled } (UIFont.TextStyle) }Declaration
Swift
@MainActor open class FUIRangeSliderFormCell : FUIInlineValidationDrawingTableViewCell<FUIRangeSliderContentView> -
A
UITableViewCellsubclass, which allows a user to view or select from a list of strings, using a Fiori-styled segmented control.
The
valueproperty of the cell is equal to theselectedSegmentIndexin the segmented control.Specifying the height for segments by setting
segmentHeightapi. By default it is set to nil which means segment will adjust its height to fit content.Color setting:
Setting text color of buttons in the cell for a state using setButtonAttributes(_:for:) api. Currently
disabled,normalandselectedare supported.let attributes = FUISegmentedControlButtonAttributes() attributes.titleAttributes = ... attributes.borderColor = ... cell.setButtonAttributes(attributes, for: .normal)Code usage:
// Optionally, create an array of value option to localized string mappings let buttonTitles: [[String: String]] = [["LO": "Low"], ["MED": "Medium"], ["HI": "High"]] // Register FUISegmentedControlFormCell in viewDidLoad() method in the controller. override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUISegmentedControlFormCell.self, forCellReuseIdentifier: FUISegmentedControlFormCell.reuseIdentifier) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUISegmentedControlFormCell.reuseIdentifier, for: indexPath) as! FUISegmentedControlFormCell cell.valueOptions = buttonTitles.flatMap { $0.map { $0.value } } cell.keyName = "Priority" cell.value = myObject.priority // String value in the valid options set: ["LO", "MED", "HI"] // MARK: implement onChangeHandler cell.onChangeHandler = { newValue in myObject.priority = buttonTitles[newValue].first!.key // lookup valid String value, from the buttonTitles array } return cell }Theming
Supported style classes
See morefdlFUISegmentedControlFormCell fdlFUISegmentedControlFormCell_keyLabelDeclaration
Swift
@available(*, deprecated, message: "This component has been replaced by FUIFilterFormCell") @MainActor open class FUISegmentedControlFormCell : FUIInlineValidationDrawingTableViewCell<FUISegmentedControlFormView> -
A
UITableViewCellsubclass, which allows a user to read or enter a set of values, using a grid of buttons. Commonly used for composing filters.
The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the property.value: An array of the selected indexes in the control. Uses the same index as thevalueOptionsarray.- `valueOptions: A String array, of titles for the buttons in the control
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value
Optionally, the developer may provide
allowsMultipleSelection: Indicates if multiple buttons may be selected simultaneously (true). Iffalse, the control behaves in “radio” mode. Defaults totrue.allowsEmptySelection: Indicates if the control allows zero items to be selected (true). If false, then once a value has been selected by the developer or user, taps by the user on the last selected item will be ignored, instead of de-selecting the item. Defaults totrue.isEditable: Indicates if the cell’s value may be modified. Defaults totrue.
Color setting:
Setting text color of filter buttons for a state using setTintColor(_:for:) api. Currently
disabled,normalandselectedare supported.cell.setTintColor(UIColor.red, for: .normal)Accessibility Identifier setting:
keyLabel.accessibilityIdentifier: Set the accessibility identifier for thekeyLabelelement within the cell.filterValueView.accessibilityIdentifier: Setting this value will make theaccessibilityIdentifierof eachfilterValueViewitem to have this value as a prefix, to avoid duplication issues.validationView.titleLabel.accessibilityIdentifier: Setting the accessibility identifier for thetitleLabelwithin thevalidationView.
The following is an example of usage in an application
UITableViewController:// optionally, create an array of value option to localized string mappings let buttonTitles: [[String: String]] = [["radius": "Distance"], ["price": "Price"], ["rating": "Ratings"], ["avail": "Availability"]] // Register FUIFilterFormCell in viewDidLoad() method in the controller. override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUIFilterFormCell.self, forCellReuseIdentifier: FUIFilterFormCell.reuseIdentifier) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUIFilterFormCell.reuseIdentifier, for: indexPath) as! FUIFilterFormCell cell.valueOptions = buttonTitles.flatMap { $0.map { $0.value }} cell.keyName = "Sort By" cell.value = [1] cell.allowsMultipleSelection = true cell.allowsEmptySelection = false // MARK: implement onChangeHandler cell.onChangeHandler = { [weak self] newValue in self.applyFilter(forDimensions: newValue) // here, the cell input is set to a filter function } return cell }## Theming Supported style classes
See morefdlFUIFilterFormCell fdlFUIFilterFormCell_keyLabel fdlFUIFilterFormCell_item_contentView fdlFUIFilterFormCell_item_titleLabel fdlFUIFilterFormCell_item_contentView_selected fdlFUIFilterFormCell_item_titleLabel_selectedDeclaration
Swift
@MainActor open class FUIFilterFormCell : FUIInlineValidationDrawingTableViewCell<FUIFilterFormView>, FUIFormCell -
A
UITableViewCellsubclass, which allows a user to read or enter a value, using a date picker.
The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the property.value: The value of the property, asDate
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value
Optionally, UITableViewController could provide
dateFormatter: A developer-definedUIDateFormatter, for transposing betweenDatetype andString.datePickerMode: TheUIDatePickerModefor the date picker. Default is.dateAndTime. Note that.countDownTimermode is not supported. Use theFUIDurationPickerFormCellfor duration values.isEditable: Indicates if the cell’s value may be modified. Defaults totrue.
Color setting:
Setting text color of filter buttons for a state using setTintColor(_:for:) api. Currently
.disabled,.normalandselectedare supported.cell.setTintColor(UIColor.red, for: .normal)The following is an example of usage in an application
UITableViewController:let dateFormatter = DateFormatter() var date: Date? override func viewDidLoad() { super.viewDidLoad() dateFormatter.dateFormat = "dd-MM-yyyy" self.tableView.register(FUIDatePickerFormCell.self, forCellReuseIdentifier: FUIDatePickerFormCell.reuseIdentifier) // ... } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUIDatePickerFormCell.reuseIdentifier, for: indexPath) as! FUIDatePickerFormCell cell.keyName = "End Date" cell.dateFormatter = dateFormatter cell.datePickerMode = .date cell.value = self.date // MARK: implement onChangeHandler cell.onChangeHandler = { [unowned self] newValue in self.date = newValue } return cell }Theming
Supported style classes
See morefdlFUIDatePickerFormCell fdlFUIDatePickerFormCell_keyLabel fdlFUIDatePickerFormCell_valueLabel fdlFUIDatePickerFormCell_selectedBackgroundView fdlFUIDatePickerFormCell_valueLabel_selectedDeclaration
Swift
@IBDesignable @MainActor open class FUIDatePickerFormCell : FUIInlineValidationTableViewCell, FUIPropertyFormCell -
A
UITableViewCellsubclass, which allows a user to read or enter a value, using a duration picker.
The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the propertyvalue: The value of the property, asTimeInterval
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value
Optionally, the developer may provide
minInterval: The minute interval to be used in the picker.isEditable: Indicates if the cell’s value may be modified. Defaults totrue.
Color configuration:
Call setTintColor(_:for:) to configure tint color for disabled, normal, selected
UIControlState. SettingtintColoris equivalent to call setTintColor(color, for: UIControlState.normal).- disabled: Color to be used when control is disabled.
- normal: Color to be used when control is enabled.
- selected: Color to be used when control is selected.
The following is an example of usage in an application
UITableViewController:override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUIDurationPickerFormCell, forCellReuseIdentifier: FUIDurationPickerFormCell.reuseIdentifier) // ... } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUIDurationPickerFormCell.reuseIdentifier, for: indexPath) as! FUIDurationPickerFormCell cell.keyName = "Duration" cell.value = myObject.eventDuration // in seconds // MARK: implement an onChangeHandler cell.onChangeHandler = { newValue in myObject.eventDuration = newValue } return cell }## Theming Supported style classes
See morefdlFUIDurationPickerFormCell fdlFUIDurationPickerFormCell_keyLabel fdlFUIDurationPickerFormCell_valueLabel fdlFUIDurationPickerFormCell_valueLabel_selectedDeclaration
Swift
@IBDesignable @MainActor public class FUIDurationPickerFormCell : FUIInlineValidationTableViewCell, FUIPropertyFormCellextension FUIDurationPickerFormCell: UIPickerViewDataSourceextension FUIDurationPickerFormCell: UIPickerViewDelegate -
A customized
UITableViewCell, which contains aUILabel, aUITextFieldand aUIPickerView. It allows users to select a single value from a set of options using a spinning wheel.
The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the propertyvalueOptions: A set of options that users can chose from.value: The value of the property, asInt
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value.
Optionally, the developer may set
isEditable: Indicates if the cell’s value may be modified. Defaults totrue.
Color setting:
Setting text color of filter buttons for a state using setTintColor(_:for:) api. Currently
.disabled,.normalandselectedare supported.cell.setTintColor(UIColor.red, for: .normal)The following is an example of usage in an application
UITableViewController:override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUIValuePickerFormCell, forCellReuseIdentifier: FUIValuePickerFormCell.reuseIdentifier) // ... } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUIValuePickerFormCell.reuseIdentifier, for: indexPath) as! FUIValuePickerFormCell cell.keyName = "Maximum Price" cell.valueOptions = ["5", "10", "15", "20", "25"] cell.value = 0 // MARK: implement an onChangeHandler cell.onChangeHandler = { [weak self] newValue in self.myObject.price = self.priceTitles[newValue].first!.key } return cell }Theming
Supported style classes
See morefdlFUIValuePickerFormCell fdlFUIValuePickerFormCell_keyLabel fdlFUIValuePickerFormCell_valueTextField fdlFUIValuePickerFormCell_valueTextField_selectedDeclaration
Swift
@IBDesignable @MainActor open class FUIValuePickerFormCell : FUIInlineValidationTableViewCell, FUIPropertyFormCell, UIPickerViewDataSource, UIPickerViewDelegate -
The reusable UI component implemented as an
UITableViewCellto display a key-value pair property, which is integrated with aFUIListPickercontroller for displaying a list of values.### Single-line version

### Multi-line version

The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the property.value: The default selections.valueOptions: The list of optional values user may choose from.allowsMultipleSelection: Indicates if user can select multiple values. Default is true, meaning by default user may select multiple values.isEditable: If the selection(s) could be modified or not. The default is true.listPicker: TheFUIListPickerfor thisFUIListPickerFormCell.
Note that the display of the selections in the
valueLabelis the responsibility of the developer if thedataSourceproperty of thelistPickeris set. Developer is to set the text of thevalueLabelto reflect the selections. Otherwise, if developer setsvalueOptionsand leavesdataSourceoflistPickerto nil, then the text invalueLabelwill be set internally.Here are the code snippets in app’s
UITableViewControllerimplementation: (The app’sUITableViewControllerneeds to be a subclass ofFUIFormTableViewController.)var propValue7: [Int] = [1, 3, 6] var valueOptions7 = ["One", "Two", "Three", "Four", "Five", "Six", "Seven"] var listPickerDataSource7 = StringListPickerDataSource(options: valueOptions7) override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUIListPickerFormCell.self, forCellReuseIdentifier: FUIListPickerFormCell.reuseIdentifier) // ... } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // ... let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell cell.keyName = "Choose Multiple" cell.value = propValue7 cell.allowsMultipleSelection = true cell.valueLabel.text = descriptionForSelectedStrings(valueOptions7, at: propValue7) // See below cell.listPicker.dataSource = listPickerDataSource7 cell.listPicker.searchResultsUpdating = listPickerDataSource7 cell.listPicker.isSearchEnabled = true cell.listPicker.prompt = "Please select multiple items" cell.listPicker.searchBar?.isBarcodeScannerEnabled = true cell.listPicker.searchBar?.barcodeScanner?.scanMode = .EAN_UPC cell.listPicker.searchBar?.barcodeScanner?.scanResultTransformer = { (scanString) -> String in return self.transformStringToSearchBar(scanResultString: scanString) } // MARK: implement onChangeHandler cell.onChangeHandler = { [weak self] newValue in self.propValue3 = newValue } return cell // ... } func descriptionForSelectedStrings(_ options: [String], at indexes: [Int]) -> String { return options.enumerated().filter({ (index, element) -> Bool in return indexes.contains(index) }).reduce ("") { string, element in return string.isEmpty ? element.1 : "\(string), \(element.1)" } }## Theming
Supported
UILabelclass paths:fdlFUIListPickerFormCell_keyLabel {} fdlFUIListPickerFormCell_keyLabel-disabled {} fdlFUIListPickerFormCell_valueLabel {}Supported
UILabelproperties:font-color: (Color) font-style: (UIFontTextStyle)Supported
UIViewclass paths:fdlFUIListPickerFormCell_selectedBackgroundView {}Supported
UIViewproperties:
See morebackground-color: (Color)Declaration
Swift
@MainActor open class FUIListPickerFormCell : FUIInlineValidationTableViewCell, FUIPickerFormCell -
FUIInlineSignatureFormCellis aUITableViewCellsubclass, which enables the drawing and capturing of a user’s signature.Usage Example:
let cell = tableView.dequeueReusableCell(withIdentifier: FUIInlineSignatureFormCell.reuseIdentifier, for: indexPath) as! FUIInlineSignatureFormCell cell.value = self.signatureImage cell.onChangeHandler = { [unowned self] newValue in self.signatureImage = newValue if let image = newValue { // save the signature image saveSignatureImage(image: image) } } return cellTheming
See Theming support in
See moreFUIInlineSignatureFormView.Declaration
Swift
@MainActor public class FUIInlineSignatureFormCell : FUIInlineValidationDrawingTableViewCell<FUIInlineSignatureFormView>, FUITableAndCollectionCellUpdate -
The protocol defines the properties and functions for listing the options in an
See moreUITableViewfor the correspondingListPickerFormCell.Declaration
Swift
@objc public protocol FUIListPicker -
An object that adopts the FUIListPickerDataSource protocol is responsible for providing the data and views required to display the list of options available in
FUIListPickerFormCellorFUIListPickerTableViewController.The data source could be sectioned by implementing the following function:
func numberOfSections(in listPicker: FUIListPicker) -> IntImportant
Only data source using unique identifier could be sectioned. That is, the propertyisDataSourceRequiringUniqueIdentifiersof theFUIListPickeris true.Implementation Note:
The list picker will not show any item if any of the required functions is not implemented.
The following optional functions are required to be implemented for data source not using unique identifier:
func numberOfRows(in listPickerTableView: UITableView) -> Int func listPickerTableView(_ tableView: UITableView, cellForRowAt index: Int, isFiltered: Bool) -> UITableViewCellThe following optional functions are required to be implemented for data source using unique identifier but not sectioned:
func numberOfRows(in listPickerTableView: UITableView) -> Int func listPickerTableView(_ tableView: UITableView, cellForRowAt index: Int, isFiltered: Bool) -> UITableViewCell func listPickerTableView(_ tableView: UITableView, cellForItemWithUniqueIdentifier uniqueIdentifier: String) -> UITableViewCell func listPickerTableView(_ tableView: UITableView, uniqueIdentifierForItemAt index: Int) -> String func listPickerTableView(_ tableView: UITableView, indexForUniqueIdentifier uniqueIdentifier: String) -> IntThe following optional functions are required to be implemented for data source using unique identifier and sectioned:
See morefunc numberOfSections(in listPicker: FUIListPicker) -> Int func listPickerTableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int func listPickerTableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath, isFiltered: Bool) -> UITableViewCell func listPickerTableView(_ tableView: UITableView, uniqueIdentifierForItemAtIndexPath indexPath: IndexPath) -> String func listPickerTableView(_ tableView: UITableView, cellForItemWithUniqueIdentifier uniqueIdentifier: String) -> UITableViewCell func listPickerTableView(_ tableView: UITableView, indexPathForUniqueIdentifier uniqueIdentifier: String) -> IndexPath?Declaration
Swift
@objc public protocol FUIListPickerDataSource -
An implementation of
FUIListPickerSearchResultsUpdatingprotocol is responsible to maintain a filtered list of options, based on the search string specified, for the correspondingFUIListPickerDataSourceimplementation.Implementation Note:
Depending on the
FUIListPickerDataSource, different optional functions in the correspondingFUIListPickerSearchResultsUpdatingare required to be implemented. The list picker will not show any item if any of the required functions is not implemented.The following optional functions are required to be implemented for data source not using unique identifier:
func listPicker(_ listPicker: FUIListPicker, filteredDataSourceContainsItemAt unfilteredIndex: Int) -> Bool func listPicker(_ listPicker: FUIListPicker, unfilteredDataSourceIndexOfItemAt filteredIndex: Int) -> IntThe following optional functions are required to be implemented for data source using unique identifier but not sectioned:
func listPicker(_ listPicker: FUIListPicker, filteredDataSourceContainsItemWithUniqueIdentifier uniqueIdentifier: String) -> BoolThe following optional functions are required to be implemented for data source using unique identifier and sectioned:
See morefunc listPicker(_ listPicker: FUIListPicker, filteredDataSourceContainsItemWithUniqueIdentifier uniqueIdentifier: String) -> BooDeclaration
Swift
@objc public protocol FUIListPickerSearchResultsUpdating -
This
FUIListPickerTableViewControlleris to show a list of table view cells to let user select one of the cell. Developer needs to provide implementation ofFUIListPickerDataSource, andFUIListPickerSearchResultsUpdatingif search is enabled, in order to useFUIListPickerTableViewController.If the
isDismissedOnSelectionproperty is set to true, and theallowsMultipleSelectionproperty is set to false, then when user selected one cell by tapping the displayed cell, theonSelectionHandlerproperty will be invoked to notify the user selection. The table view will then be dismissed.There will be a “Done” button shown in the navigation bar if the
isDismissedOnSelectionproperty is set to false or theallowsMultipleSelectionproperty is set to true. TheonSelectionHandlerproperty will be invoked after user tapped the “Done” button if theallowsMultipleSelectionproperty is set to false, or theonMultipleSelectionHandlerproperty will be invoked if theallowsMultipleSelectionproperty is set to true. Then the table view will be dismissed.There will be a “Select All” button in the “All” section header, if multiple selections is allowed and not all items are selected. All items are selected when the “Select All” button is tapped. Once all items are selected, the button title will change to “Deselect All”. All items are de-selected when “Deselect All” button is tapped.
Also, a “Deselect All” button will be in the “Selected” section header when multiple selections is allowed. The “Selected” section will appear if the items in the list could not be displayed in one screen, and there are one or more items selected. All selected items will be de-selected when “Deselect All” button is tapped.
Here is a code snippet of a typical usage:
let listPickerTableViewController = createInstanceFromStoryboard() var listPicker = listPickerTableViewController.listPicker listPicker.title = "Magic School" listPicker.register(FUIObjectTableViewCell.self, forCellReuseIdentifier: FUIObjectTableViewCell.reuseIdentifier) listPicker.dataSource = self.objectCellListPickerDataSource listPicker.prompt = "Select One" listPicker.estimatedRowHeight = 98 listPicker.isSearchEnabled = true listPicker.searchResultsUpdating = self.objectCellListPickerDataSource listPicker.isBarcodeScannerEnabled = true listPicker.barcodeScanMode = .all listPicker.barcodeScanResultTransformer = { (scanString) -> String in return "S" } listPickerTableViewController.onSelectionHandler = { self.select1Result.text = self.objectCellListPickerDataSource.descriptionForSelectedItems(at: [$0]) } listPickerTableViewController.showsCancelButton = true listPickerTableViewController.isDismissedOnSelection = false // Select item at index 4 as default, which is the 5th item. listPickerTableViewController.selectItem(4) let navController = UINavigationController(rootViewController: listPickerTableViewController) self.present(navController, animated: true, completion: nil)Theming
Supported style classes
See morefdlFUIListPickerTableViewController fdlFUIListPickerTableViewController_cancelItem fdlFUIListPickerTableViewController_sectionHeaderTitleLabel fdlFUIListPickerTableViewController_listTextLabelDeclaration
Swift
@MainActor open class FUIListPickerTableViewController : UITableViewController, UISearchResultsUpdating, UISearchBarDelegateextension FUIListPickerTableViewController: FUIBarcodeScanViewControllerDelegateextension FUIListPickerTableViewController: UISheetPresentationControllerDelegate -
- The reusable UI component implemented as an UITableViewCell to manage selecting attachments.
FUIAttachmentsFormCelluses aFUIAttachmentsViewControllerto display the title of the cell and a collection of icons to represent the attachments. The attachment icon size may change, depends on the system font size settings. The controller arranges the attachment icons in such a manner that as many icons to be fitted in a row, and as many rows to display all the attachment icons. It will also try to make the row spacing equal to the spacing between icons. However, the row spacing is limited to 20 pixels maximum.Developers should use the property
attachmentsControllerto provide attachment information; thedelegate, thedataSourceand the list ofFUIAttachmentActionimplementations for the desired type of attachments. The app can use the built-in types or implement additional types as desired.Color settings:
Setting tintColor for add button for a state using setTintColor(_:for:) api. Currently
normaland.selectedare supported.cell.setTintColor(UIColor.red, for: .normal)There are three built-in
FUIAttachmentAction:FUIAddPhotoAttachmentAction: Choose photo from the photo library.FUITakePhotoAttachmentAction: Take photo using the camera.FUIDocumentPickerAttachmentAction: Select file using standardUIDocumentPickerViewController.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUIAttachmentsFormCell.reuseIdentifier, for: indexPath) as! FUIAttachmentsFormCell cell.attachmentsController.delegate = self cell.attachmentsController.dataSource = self cell.attachmentsController.showAlertWhenDeleting = true let addPhotoAction = FUIAddPhotoAttachmentAction() addPhotoAction.delegate = self cell.attachmentsController.addAttachmentAction(addPhotoAction) let takePhotoAction = FUITakePhotoAttachmentAction() takePhotoAction.delegate = self cell.attachmentsController.addAttachmentAction(takePhotoAction) let filePickerAction = FUIDocumentPickerAttachmentAction() filePickerAction.delegate = self cell.attachmentsController.addAttachmentAction(filePickerAction) return cell } var attachmentURLs: [URL] = [URL]() // MARK: FUIAttachmentsViewControllerDataSource methods func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, iconForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? { let urlString = self.attachmentURLs[index].absoluteString guard let image = self.attachmentThumbnails[urlString] else { return nil } return (image!, .scaleAspectFill) } func numberOfAttachments(in attachmentsViewController: FUIAttachmentsViewController) -> Int { return attachmentURLs.count } func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, urlForAttachmentAtIndex index: Int) -> URL? { return attachmentURLs[index] } func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, titleForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? { return "attachment title" } func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, subtitleForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? { return "attachment subtitle" } func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, footnoteForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? { return "attachment footnote" } // MARK: FUIAttachmentsViewControllerDelegateMethods func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, couldNotPresentAttachmentAtIndex index: Int) { } func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, didPressDeleteAtIndex index: Int) { self.attachmentURLs.remove(at: index) self.tableView.reloadSections(IndexSet(integer:attachmentSection), with: .automatic) } func focusOnNewAttachment() { DispatchQueue.main.async { if let cell = self.tableView.visibleCells.last as? FUIAttachmentsFormCell { // find the attachment cell if let newDoc = cell.accessibilityElements?.last { UIAccessibility.post(notification: .layoutChanged, argument: newDoc) } } } } //MARK: FUIAddPhotoAttachmentActionDelegate func addPhotoAttachmentAction(_ action: FUIAddPhotoAttachmentAction, didSelectPhoto asset: PHAsset, at url: URL) { setupThumbnails(url, with: asset) self.addAttachmentURL(url) } //MARK: FUITakePhotoAttachmentActionDelegate func takePhotoAttachmentAction(_ action: FUITakePhotoAttachmentAction, didTakePhoto asset: PHAsset, at url: URL) { setupThumbnails(url, with: asset) self.addAttachmentURL(url) } func addAttachmentURL(_ url: URL) { self.attachmentURLs.append(url) DispatchQueue.main.async { self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic) self.tableView.scrollToRow(at: IndexPath(row: 0, section: self.attachmentSection) , at: .middle, animated: true) if UIAccessibility.isVoiceOverRunning { focusOnNewAttachment() } } } func setupThumbnails(_ url: URL, with asset: PHAsset) { let imageManager = PHImageManager.default() imageManager.requestImage(for: asset, targetSize: CGSize(width: 80, height: 80), contentMode: .default, options: nil, resultHandler: { image, array in self.attachmentThumbnails[url.absoluteString] = image DispatchQueue.main.async { self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic) self.tableView.scrollToRow(at: IndexPath(row: 0, section: self.attachmentSection) , at: .middle, animated: true) } }) } //MARK: FUIDocumentPickerAttachmentActionDelegate { var documentPicker: UIDocumentPickerViewController { return UIDocumentPickerViewController(documentTypes: ["public.data"], in: .import) } func documentPickerAttachmentAction(_ action: FUIDocumentPickerAttachmentAction, didPickFileAt url: URL) { if let savedUrl = saveFileToTempFolder(url) { self.addAttachmentURL(savedUrl) } self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic) if UIAccessibility.isVoiceOverRunning { focusOnNewAttachment() } }## Theming
Supported
TEXTclass paths:fdlFUIAttachmentsFormView_attachmentTitleLabel {} fdlFUIAttachmentsViewController_alertActionTitle {} fdlFUIFileThumbnailCollectionItemView_titleLabel {} fdlFUIThumbnailCollectionItemView_subtitle {} fdlFUIThumbnailCollectionItemView_footnote {}Supported
TEXTproperties:font-color: Color; font-style: UIFontTextStyle;Supported
IMAGEclass paths:fdlFUIFileThumbnailCollectionItemView_detailImageView {}Supported
IMAGEproperties:tint-color: Color;Supported
BUTTONclass paths:fdlFUIAddButtonCell_addButton {}Supported
BUTTONproperties:image: Image; tint-color: Color;Supported
CELLclass paths:fdlFUIAttachmentsFormCell_thumbnailCell {} fdlFUIAttachmentsFormCell_addButtonCell {}Supported
CELLproperties:border-color: Color; border-width: Integer; corner-radius: Integer;Supported style classes
See moreDeclaration
Swift
@IBDesignable @MainActor open class FUIAttachmentsFormCell : FUIInlineValidationTableViewCell -
Simple
UITableViewCellsubclass, containing aUIButtoninstance which can be aligned to 3FUIHorizontalAlignmentpositions:.left,.center,.right.
Color settings:
Setting tintColor for button for a state using setTintColor(_:for:) api. Currently
disabled,normalandselectedare supported.cell.setTintColor(UIColor.red, for: .normal)Usage:
Implement the action handler for the
UIButtoninstance, to respond toUIControlevents.Theming
Supported style classes
See morefdlFUIButtonFormCell fdlFUIButtonFormCell_buttonDeclaration
Swift
@IBDesignable @MainActor open class FUIButtonFormCell : FUIInlineValidationTableViewCell -
FUIInlineValidationView is a
UIViewcontains aUILabel. It is used byFUIInlineValidationTableViewCellas a validation view appearing at the bottom to show the validation message.Theming
Supported style classes
See morefdlFUIInlineValidationView fdlFUIInlineValidationView_titleLabel fdlFUIInlineValidationView_separatorView fdlFUIInlineValidationView_backgroundViewDeclaration
Swift
@MainActor open class FUIInlineValidationView : NibDesignable -
FUIInlineValidationTableViewCellis a base class forFUIFormCells that need to support validation handling. The validation view will appear at the bottom of cell if validation message is set.This class is typically not used by developer. Most of form cells are subclassing this class. To enable validation message on form cells by setting
validationMessageproperty.Code usage:
Set validationMessage on form cell.
See moreoverride func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUITitleFormCell.reuseIdentifier, for: indexPath) as! FUITitleFormCell //Configure your cell cell.validationMessage = "Validation msg" }Declaration
Swift
@MainActor open class FUIInlineValidationTableViewCell : NibDesignableFUIBaseTableViewCell, FUIInlineValidation, FUIAccessoryViewDelegate -
FUIFilterFeedbackControlprovides an easy way for programmers to represent a list of applied filters. ThisFUIFilterFeedbackControlusually appears at the top of the screen above a UITableView. Although you can set this view to any height, it is recommended to set the height of this cell toCGFloat(44). And set its height constraint to the same value.Developers can use in Interface Builder by adding a UIView to their storyboard or XIB, then setting its class to
FUIFilterFeedbackControl. Then set thefilterGroups, andfilterResultsUpdaterproperties.@IBOutlet var filterFeedbackControl: FUIFilterFeedbackControl! // ... var sortGroup = FUIFilterGroup() var mileGroup = FUIFilterGroup() var nearGroup = FUIFilterGroup() override func viewDidLoad() { super.viewDidLoad() let sortDistanceItem = FUIFilterItem("Sort: Distance", isFavorite: false, isActive: true) let sortPriceItem = FUIFilterItem("Sort: Price", isFavorite: false, isActive: false) let sortRatingsItem = FUIFilterItem("Sort: Ratings", isFavorite: false, isActive: false) let sortAvailabilityItem = FUIFilterItem("Sort: Availability", isFavorite: false, isActive: false) let mile1Item = FUIFilterItem("0.1 mi", isFavorite: true, isActive: false) let mile2Item = FUIFilterItem("0.2 mi", isFavorite: true, isActive: false) let mile3Item = FUIFilterItem("0.3 mi", isFavorite: true, isActive: false) let mile4Item = FUIFilterItem("0.4 mi", isFavorite: true, isActive: true) sortGroup.items = [sortDistanceItem, sortPriceItem, sortRatingsItem, sortAvailabilityItem] sortGroup.allowsEmptySelection = false sortGroup.isMutuallyExclusive = true mileGroup.items = [mile1Item, mile2Item, mile3Item, mile4Item] mileGroup.allowsEmptySelection = true mileGroup.isMutuallyExclusive = true let nearGasItem = FUIFilterItem("Nearby Gas", isFavorite: true, isActive: false) let nearCoffeeItem = FUIFilterItem("Nearby Coffee", isFavorite: true, isActive: false) let nearRestaurantsItem = FUIFilterItem("Nearby Restaurants", isFavorite: true, isActive: false) nearGroup.items = [nearGasItem, nearCoffeeItem, nearRestaurantsItem] nearGroup.allowsEmptySelection = true nearGroup.isMutuallyExclusive = false filterFeedbackControl.filterGroups = [sortGroup, mileGroup, nearGroup] filterFeedbackControl.filterResultsUpdater = self // ... } func updateFilterResults(for filterFeedbackControl: FUIFilterFeedbackControl) { let effectiveItems = filterFeedbackControl.filterItems // ... }To keep selected item in the original order, use following code:
filterFeedbackControl.keepsItemOrderOnSelection = trueImplement the
FUIFilterFeedbackControlDelegateto set cell properties such as accessibility:let myDelegate = MyDelegate() filterFeedbackControl.delegate = myDelegate class MyDelegate: FUIFilterFeedbackControlDelegate { func filterFeedbackControl(_ filterFeedbackControl: FUIFilterFeedbackControl, willDisplay cell: UICollectionViewCell, with item: FUIFilterItem) { cell.accessibilityIdentifier = "identifier" } }Theming
FUIFilterFeedbackControlis using a list ofSegmentedControlcomponentes. Therefore, theming ofFUIFilterFeedbackControlshould be using theSegmentedControltheming elements.fdlSegmentedControl_item_contentView { border-color: @primary4; } fdlSegmentedControl_item_titleLabel { font-color: @primary2; } fdlSegmentedControl_item_contentView_selected { border-color: @tintColorDark; } fdlSegmentedControl_item_titleLabel_selected { font-color: @tintColorDark; }Theming
Supported style classes
See more// Customize border color fdlFUIFilterFeedbackControl_lineViewDeclaration
Swift
@MainActor open class FUIFilterFeedbackControl : UIView, FUIViewBorderDrawing -
This protocol is to be used in
See moreFUIFilterFeedbackControlfor updateing the results based on the changes in filters.Declaration
Swift
public protocol FUIFilterResultsUpdating : AnyObject -
A
See moreFUIFilterGrouprepresents a group of relatedFUIFilterItemobjects.Declaration
Swift
open class FUIFilterGroup -
A
See moreFUIFilterItemrepresent one “Filter” item to be displayed on theFUIFilterFeedbackControlview.Declaration
Swift
public class FUIFilterItem : Equatable -
FUISortFilterViewControllerallows users to narrow down results from a long list by setting criteria. Users are able to reset filters and return to the initial list.Various
ControlTypes, such as switch, filter, rating, etc. are supported for sort and filter criteria.Initialization and Configuration Example:
let vc = FUISortFilterViewController() // This is required. This is a 2D array of sort and filter criteria. The first dimension of the array is `UITableView` sections and the second dimension is `ControlTypes(cells`) for that section. vc.values = [ [ .filter([0], ["Distance", "Availability", "Ratings", "Price"], "Sort by", false, true) ], [ .switch(true, "Show Favorites"), .listPicker([0], ["None", "John Smith", "Mary Jones", "Ronald Archer"], "Assigned To", false, false, true, true), .switch(false, "Show My Work Orders"), .filter([0, 2], ["Received", "Started", "Hold", "Transfer", "Completed", "Pending Review", "Rejected"], "Mobile Status"), ], [ .datePicker(Date(), "Date and Time") ] ] // This is required for `FUISortFilterViewController` to invoke it to update the UI to show the number of results based on the current sort and filter criteria. vc.onChangeHandler = { [weak self] values, change in // Returns the total number of items when no filter criteria have been provided. if values.isEmpty { return 20 } /// your code goes here return filteredNum } // Required. vc.completionHandler = { [weak self] values, filteredNum in /// your code goes here } let nav = UINavigationController(rootViewController: vc) vc.modalPresentationStyle = .popover vc.popoverPresentationController?.barButtonItem = sender self.present(nav, animated: true)Note:
The title and subtitle for
UINavigationBarand title for the Action button in the bottomUIToolbarcan be customized as well./// Customize the title and subtitle for `UINavigationBar`. This is optional. vc.titleAndSubtitleHandler = { filteredResult, totalNum in ("Filter", "Orders \(filteredResult) of \(totalNum)") } /// Customize the title for the action button. This is optional. vc.actionButtonTitleHandler = { filteredResult in "Show \(filteredResult) orders" }FUISortFilterFormDelegateExample:vc.sortFilterFormDelegate = self
See moreextension YourDelegateClass: FUISortFilterFormDelegate { func cell(_ vc: FUISortFilterViewController, controlType: FUISortFilterViewController.ControlType, at indexPath: IndexPath) -> UITableViewCell? { if indexPath == IndexPath(row: 0, section: 8) { let tableView = vc.tableView return tableView?.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) } return nil } func configCell(_ vc: FUISortFilterViewController, controlType: FUISortFilterViewController.ControlType, at indexPath: IndexPath, cell: UITableViewCell) -> UITableViewCell { if indexPath == IndexPath(row: 0, section: 1) { if let theCell = cell as? FUIListPickerFormCell { theCell.isPickerDismissedOnSelection = true theCell.alwaysShowValueTextOnBottom = true return theCell } } return cell } }Declaration
Swift
@MainActor public class FUISortFilterViewController : FUIFormTableViewController -
The reusable UI component implemented as an
UITableViewCellto display or be edited as a stepper.
A stepper is a visual representation of a user’s progress through a series of steps in a task, indicating how much the user has completed or how far they are from completing the task.
The developer should set the following properties on the cell, in their implementation of
UITableViewDataSourcecellForRow(at:)function:keyName: The key name of the property.value: The numeric value of the stepper.
And an
onChangeHandler:onChangeHandler: a handler closure, which is invoked on changes to the value
Optionally, the developer may provide
hintText: hint text.isEditable: Indicates whether the cell’s value can be modified. The default istrue.maximumValue: The highest possible numeric value for the stepper. The default is 100.minimumValue: The lowest possible numeric value for the stepper. The default is 0.stepValue: The step or increment value for the stepper. The default is 1, must be greater than 0.
The following is an example of usage in an application
UITableViewController:override func viewDidLoad() { super.viewDidLoad() self.tableView.register(FUIStepperFormCell.self, forCellReuseIdentifier: FUIStepperFormCell.reuseIdentifier) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: FUIStepperFormCell.reuseIdentifier, for: indexPath) as! FUIStepperFormCell cell.keyName = "Normal Stepper" cell.value = 5 cell.hintText = "hint text" // MARK: implement onChangeHandler cell.onChangeHandler = { newValue in // ... } cell.maximumValue = 10 cell.minimumValue = 0 // custom colors and fonts cell.setAttributes([.fuiBorderColor: UIColor.systemPurple], for: .title, state: .highlighted) cell.setAttributes([.fuiBorderColor: UIColor.systemYellow], for: .title, state: .normal) return cell }## Customize Style Using
tintAttributesSupported
keyView:setAttributes([.foregroundColor:, .font], for: .title, state: { .normal | .highlighted | .disabled })or directly set
textColorandfontfor the title.Supported
valueText:setAttributes([.foregroundColor:, .font], for: .valueText, state: { .normal | .disabled }) addAttributes([.fuiBorderColor:], for: .valueText, state: { .normal | .highlighted | .disabled })or directly set
textColorandfontfor the valueTextField.Supported
increaseButtonanddecreaseButton:setAttributes([.foregroundColor:], for: .icons, state: { .normal | .disabled })Supported
hintView:setAttributes([.foregroundColor:, .font:], for: .subtitle, state: { .normal | .disabled })###
.nssThemeSupported
keyView:fdlFUIStepperFormCell_keyText { font-color { -highlighted | -disabled } (Color) font-style { -highlighted | -disabled } (UIFont.TextStyle) }Supported
valueText:fdlFUIStepperFormCell_valueText { font-color { -disabled } (Color) font-style { -disabled } (UIFont.TextStyle) border-color { -highlighted | -disabled } (Color) }Supported
BUTTONclass paths:fdlFUIStepperFormCell_increaseButton { font-color { -disabled } (Color) } fdlFUIStepperFormCell_decreaseButton { font-color { -disabled } (Color) }Supported
hintView:
See morefdlFUIStepperFormCell_hintText { font-color { -disabled } (Color) font-style { -disabled } (UIFont.TextStyle) }Declaration
Swift
@MainActor open class FUIStepperFormCell : FUIInlineValidationDrawingTableViewCell<FUIStepperView>, FUIFormCellextension FUIStepperFormCell: FUITintAttributesProvider