KCSForm-iOS
KCS Form is a library to help you build iOS UI forms using pre-built input types. The SDK is easy to use and easy to style to make form creation effortless.
Requirements
- iOS 11.0+
- Xcode 10.1+
- Swift 4.2+
Author
Matthew Patience
Dependencies
These are already imported as pod dependancies, but thanks to the following libraries:
Installation
pod 'KCSForm-iOS'
Usage
Create an instance of FormViewController and implement it's delegate:
let formController = FormViewController()
formController.delegate = self
Stylise your form, by default the form has no margins, color, or fonts. Below are some of the available style options (See FormStyle class for all options), feel free to submit PRs to add more if required.
let style = FormStyle()
style.fieldTitleColor = .black
style.fieldEntryColor = .black
style.fieldPlaceholderColor = .gray
style.fieldBorderColor = .black
style.fieldErrorColor = .red
style.fieldDisabledColor = .gray
style.buttonLabelColor = .black
style.sectionTitleColor = .black
style.titleColor = .black
style.subTitleColor = .gray
style.setFormMargins(leading: 20, trailing: 20, top: 20, bottom: 20)
style.interItemFieldSpacing = 20
style.lineSpacing = 20
style.fieldTitleBottomMargin = 10
style.sectionTitleTopMargin = 20
style.sectionTitleBottomMargin = 0
style.fieldCornerRadius = 2
style.fieldBorderWidth = 1
style.checkboxItemSpacing = 8
style.titleSubTitleTopMargin = 20
style.titleSubTitleBottomMargin = 10
style.titleSubTitleVerticalSpacing = 10
style.errorTopMargin = 5
style.fieldTitleFont = UIFont.systemFont(ofSize: 14, weight: .medium)
style.sectionTitleFont = UIFont.systemFont(ofSize: 24, weight: .bold)
style.fieldButtonFont = UIFont.systemFont(ofSize: 18, weight: .bold)
style.titleFont = UIFont.systemFont(ofSize: 18, weight: .medium)
style.subTitleFont = UIFont.systemFont(ofSize: 14, weight: .regular)
style.fieldErrorFont = UIFont.systemFont(ofSize: 14, weight: .regular)
style.textFieldStyle = .box
style.bounce = false
formViewController.setStyle(style)
Lastly, create the cells that will be in your form. Each cell will require a unique identifier, it is recommended that you use an enum to identify each cell.
enum CellId: Int {
case firstName
case lastName
case email
case phone
}
Each cell will require a specific data object that will define it's content and appearance. Width is measured in percentage of the overall width of each form row since the form uses a flow layout.
var cells = [FormViewController.Cell]()
let firstNameData = FormTextFieldCell.Data(title: "First Name", text: "", placeholder: "John", keyboardType: .default, returnKeyType: .next, formattingPattern: nil, capitalizationType: .words, isEditable: true, errorText: "Error!!!"))
cells.append(FormViewController.Cell(id: CellId.firstName.rawValue, type: .text, widthPercentage: 0.5, data: firstNameData)
formController.setCells(cells)
formController.reloadCollectionView()
Whenever the input content of a cell is changed, a FormViewControllerDelegate callback will be triggered depending on the cell type. For example, the updatedText callback would be triggered in the case of a FormTextFieldCell or FormPasswordCell text change.
func formViewController(_ controller: FormViewController, updatedText: String?, forCellId id: Int) {
switch (id) {
case CellId.firstName.rawValue:
print(updatedText)
break
default:
break
}
}
Available Form Components
Section Title
cells.append(FormViewController.Cell(id: CellId.section1.rawValue, type: .title, widthPercentage: 1.0,
data: FormSectionTitleCell.Data(title: "Section One")))
Text Field
cells.append(FormViewController.Cell(id: CellId.email.rawValue, type: .text, widthPercentage: 1.0,
data: FormTextFieldCell.Data(title: "Email", text: "", placeholder: "[email protected]", keyboardType: .emailAddress, returnKeyType: .next, formattingPattern: nil, capitalizationType: .none, isEditable: true, errorText: nil)))
Password
cells.append(FormViewController.Cell(id: CellId.password.rawValue, type: .password, widthPercentage: 1.0,
data: FormPasswordCell.Data(title: "Password", password: "", placeholder: "********")))
Button Options
cells.append(FormViewController.Cell(id: CellId.gender.rawValue, type: .buttonOptions, widthPercentage: 1.0,
data: FormButtonOptionsCell.Data(title: "Gender", multiSelect: false, options: ["Male", "Female", "Other"])))
Tags
cells.append(FormViewController.Cell(id: CellId.gender.rawValue, type: .buttonOptions, widthPercentage: 1.0,
data: FormButtonOptionsCell.Data(title: "Gender", multiSelect: false, options: ["Male", "Female", "Other"])))
Checkbox Options
cells.append(FormViewController.Cell(id: CellId.contactOptions.rawValue, type: .checkboxOptions, widthPercentage: 1.0,
data: FormCheckboxOptionsCell.Data(title: "Contact Methods", options: ["Phone", "Email", "Snail Mail", "Carrier Pidgeon"], optionStates: ["Phone": false, "Email": false])))
Dropdown
cells.append(FormViewController.Cell(id: CellId.country.rawValue, type: .dropdown, widthPercentage: 1.0,
data: FormDropdownCell.Data(title: "Country", selection: nil, placeholder: "Select a country", isEditable: true, options: ["Canada", "USA", "Mexico", "Westeros"])))
cells.append(FormViewController.Cell(id: CellId.eyeColor.rawValue, type: .dropdown, widthPercentage: 1.0,
data: FormDropdownCell.Data(title: "Eye Color:", selection: nil, placeholder: "Select a color", isEditable: true, options: [FormColor(.blue, "Blue"), FormColor(.black, "Black"), FormColor(.brown, "Brown"), FormColor(.cyan, "Cyan"), FormColor(.gray, "Gray"), FormColor(.green, "Green", available: false), FormColor(.magenta, "Magenta"), FormColor(.orange, "Orange"), FormColor(.purple, "Purple")])))
Label
cells.append(FormViewController.Cell(id: CellId.someLabel.rawValue, type: .label, widthPercentage: 1.0,
data: FormLabelCell.Data(text: NSAttributedString(string: "I am a label!"))))
Title Subtitle
cells.append(FormViewController.Cell(id: CellId.loremIpsum.rawValue, type: .titleSubtitle, widthPercentage: 1.0,
data: FormTitleSubtitleCell.Data(title: "Lorem Ipsum", subTitle: "Lorem ipsum dolor sit amet")))
Button
cells.append(FormViewController.Cell(id: CellId.save.rawValue, type: .button, widthPercentage: 1.0,
data: FormButtonCell.Data(title: "Save")))
Color Options
cells.append(FormViewController.Cell(id: CellId.favoriteColor.rawValue, type: .colorOptions, widthPercentage: 1.0,
data: FormColorOptionsCell.Data(title: "Favorite Color:", multiSelect: false, selectedOptionIndex: nil, options: [FormColor(.blue, "Blue"), FormColor(.black, "Black"), FormColor(.brown, "Brown"), FormColor(.cyan, "Cyan"), FormColor(.gray, "Gray"), FormColor(.green, "Green", available: false), FormColor(.magenta, "Magenta"), FormColor(.orange, "Orange"), FormColor(.purple, "Purple")])))
Spacer
cells.append(FormViewController.Cell(id: CellId.spacer.rawValue, type: .spacer, widthPercentage: 1.0, data: FormSpacerCell.Data(height: 20)))
NEED SOMETHING CUSTOM?
No problem, just create your own collection view cell, set the cell type to "custom", and then tell it what class to use. (Note: Must be an XIB)
cells.append(FormViewController.Cell(id: <EXAMPLE_ID>, type: .custom, widthPercentage: 1.0, data: nil, customCell: ExampleCustomCell.self))
You will also need to implement the FormViewControllerDelegate updateCustomCell callback to update the cell's content when it is about to be displayed:
func formViewController(_ controller: FormViewController, updateCustomCell cell: UICollectionViewCell, forCellId id: Int) -> UICollectionViewCell {
if id == CellId.optIn.rawValue {
if let cell = cell as? ExampleCustomCell {
cell.update(title: "Lorem ipsum")
}
}
return cell
}
License
This repository is licensed under the MIT License
https://opensource.org/licenses/MIT
Community and Contributing
We welcome your contributions. Like all Kinetic Cafe open source projects, is under the Kinetic Cafe Open Source Code of Conduct.