Flix
Flix copied to clipboard
iOS reusable form library in Swift.
Flix is a flexible iOS framework for creating dynamic forms with UITableView
or UICollectionView
.
Features
- [x] Supports no reused when you need.
- [x] Supports reused for list when you need.
- [x] Supports nested forms.
- [x] Supports add, delete and insert
- [x] Supports Storyboard design
- [x] Example app available!
- [x] Works with
UITableView
andUICollectionView
Flix focus on combining cells of UICollectionView
or UITableView
, it don't care about the view layout, business logic. So you can easily build custom form using Flix.
Preview
Requirements
- Xcode 10.2+
- Swift 5+
- RxSwift 5.0+
- RxDataSources 4.0+
Installation
CocoaPods
pod 'Flix', '~> 4.0'
Principle
Each provider will generate a number of nodes (cells), then combines those providers according to the sequence.
Tutorial - A Simple Settings Page
When creating a settings page, we don't want to some cells be reused, for example Profile Cell, Airplane Mode Cell. This looks like creating a static tableView on Storyboard.
To create one profile cell, we just need to create a UniqueCustomTableViewProvider
and configure the style and add some views:
let profileProvider = UniqueCustomTableViewProvider()
profileProvider.itemHeight = { _ in return 80 }
profileProvider.accessoryType = .disclosureIndicator
|
![]() |
---|
Now, we have a profile cell for the settings page, considering we might use this provider on another UITableView
.
We should make a Class for profileProvider
.
We can inherit from UniqueCustomTableViewProvider
:
class ProfileProvider: UniqueCustomTableViewProvider {
let avatarImageView = UIImageView()
let nameLabel = UILabel()
let subTitleLabel = UILabel()
init(avatar: UIImage, name: String) {
super.init()
self.itemHeight = { _ in return 80 }
self.accessoryType = .disclosureIndicator
avatarImageView.image = avatar
self.contentView.addSubview(avatarImageView)
nameLabel.text = name
self.contentView.addSubview(nameLabel)
subTitleLabel.text = "Apple ID, iCloud, iTunes & App Store"
self.contentView.addSubview(subTitleLabel)
}
}
or just implement the protocol UniqueAnimatableTableViewProvider
:
class ProfileProvider: UniqueAnimatableTableViewProvider {
let avatarImageView = UIImageView()
let nameLabel = UILabel()
let subTitleLabel = UILabel()
init(avatar: UIImage, name: String) {
avatarImageView.image = avatar
nameLabel.text = name
subTitleLabel.text = "Apple ID, iCloud, iTunes & App Store"
}
func onCreate(_ tableView: UITableView, cell: UITableViewCell, indexPath: IndexPath) {
cell.accessoryType = .disclosureIndicator
cell.contentView.addSubview(avatarImageView)
cell.contentView.addSubview(nameLabel)
cell.contentView.addSubview(subTitleLabel)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath, value: ProfileProvider) -> CGFloat? {
return 80
}
}
But in reality, the profile cell is placed in a section.
We can use SectionProfiler
:
let profileSectionProvider = SpacingSectionProvider(
providers: [profileProvider],
headerHeight: 35,
footerHeight: 0
)
self.tableView.flix.build([profileSectionProvider]) |
![]() |
---|
Then add more providers:
let profileProvider = ProfileProvider(
avatar: #imageLiteral(resourceName: "Flix Icon"),
name: "Flix")
let profileSectionProvider = SpacingSectionProvider(
providers: [profileProvider],
headerHeight: 35,
footerHeight: 0)
let airplaneModeProvider = SwitchTableViewCellProvider(
title: "Airplane Mode",
icon: #imageLiteral(resourceName: "Airplane"),
isOn: false)
let wifiProvider = DescriptionTableViewCellProvider(
title: "Wi-Fi",
icon: #imageLiteral(resourceName: "Wifi"),
description: "Flix_5G")
let bluetoothProvider = DescriptionTableViewCellProvider(
title: "Bluetooth",
icon: #imageLiteral(resourceName: "Bluetooth"),
description: "On")
let cellularProvider = DescriptionTableViewCellProvider(
title: "Cellular",
icon: #imageLiteral(resourceName: "Cellular"))
let hotspotProvider = DescriptionTableViewCellProvider(
title: "Personal Hotspot",
icon: #imageLiteral(resourceName: "Personal Hotspot"),
description: "Off")
let carrierProvider = DescriptionTableViewCellProvider(
title: "Carrier",
icon: #imageLiteral(resourceName: "Carrier"),
description: "AT&T")
let networkSectionProvider = SpacingSectionProvider(
providers: [
airplaneModeProvider,
wifiProvider,
bluetoothProvider,
cellularProvider,
hotspotProvider,
carrierProvider
],
headerHeight: 35,
footerHeight: 0
)
self.tableView.flix.build(
[profileSectionProvider, networkSectionProvider]
)
|
![]() |
---|
Until now, we just use one provider to generate one cell. We can also create a provider for a group of cells.
let appSectionProvider = SpacingSectionProvider(
providers: [AppsProvider(apps: [
App(icon: Wallet, title: "Wallet"),
App(icon: iTunes, title: "iTunes"),
App(icon: Music, title: "Music"),
App(icon: Safari, title: "Safari"),
App(icon: News, title: "News"),
App(icon: Camera, title: "Camera"),
App(icon: Photos), title: "Photo")
])],
headerHeight: 35,
footerHeight: 35
)
self.tableView.flix.build([
profileSectionProvider,
networkSectionProvider,
appSectionProvider]
)
|
![]() |
---|
Look like good.
Actually Flix supports more build list view function, you can easily create a page with all kinds of linkage effects (such as Calendar Events, GitHub Signup). More example are available in the Example Folder.
Contributing
- Please fork this project
- Implement new methods or changes。
- Write appropriate docs and comments in the README.md
- Submit a pull request.
Contact
Raise an Issue or hit me up on Twitter @Songxut.
License
Flix is released under an MIT license. See LICENSE for more information.