KTTagsView offers a Swift UIView
and protocols to help you to display your own custom views as "tags". This library is very useful when you need to display your tags in a UIScrollView
, as it is handled by a UIView
.
💡 You can display tags using a
UICollectionView
and itsUICollectionLayout
, but its not very suitable to deal with a scrollable element being inside another scrollable element, making it not scrollable etc...
It also includes a few styling properties:
- horizontal alignment: the horizontal alignment of the tags (
left
,center
orright
) - vertical alignment: the vertical alignment of the tags (
top
,center
orbottom
). - intertag spacing: the minimum spacing between tags.
💡 To run the example project, clone the repo, pod install, and run the iOS application.
The preferred installation method is with CocoaPods. Add the following to your Podfile
:
pod 'KTTagsView', '~> 1.0.1'
For Carthage, add the following to your Cartfile
:
github "iKiKi/KTTagsView"
1) Implement your own views you need to display as tags (as usual).
They just need them to conform to the `TagSizable` protocol.
public protocol TagSizable: class {
associatedtype Tag
static func preferredSize(with contentSize: CGSize, tag: Tag, at index: Int) -> CGSize
}
💡 This protocol allows you to manipulate your own type representing a tag, through the
associatedtype
.
Example with just a String
as tag:
import KTTagsView
final class MyTagView: UIView {
// Implement it as usual
}
// MARK: - TagSizable
extension MyTagView: TagSizable {
static func preferredSize(with contentSize: CGSize, tag: String, at index: Int) -> CGSize {
//TODO: return the size of your view from the tag
}
}
⚠️ Make sure the returned size width do not exceed the contentSize width.
2) Implement a TagsProvider
objet. This aims to hold your tags data and the graphics context to display them using KTTagsView.
This protocol is very simple.
public protocol TagsProvider: TagSizable {
var tags: [Tag] { get }
var horizontalAlignment: TagsView.HorizontalAlignment { get }
var verticalAlignment: TagsView.VerticalAlignment { get }
var minimumIntertagSpacing: CGFloat { get }
}
- tags: the property holding tags data.
- horizontalAlignment: the horizontal alignment of the tags (left, center or right). This is
.left
by default. - verticalAlignment: the vertical alignment of the tags (top, center or bottom). This is
.top
by default. - minimumIntertagSpacing: the spacing between tags.
💡 Note that
TagsProvider
is himselfTagSizable
. In fact, it is expected the object to return the size provided by your views direclty.
Please find an example below with an object called TagsViewModel
(always with tags data as String
):
import KTTagsView
final class TagsViewModel: TagsProvider {
var tags: [String] {
//TODO: return your
}
var horizontalAlignment: TagsView.HorizontalAlignment = .left
var verticalAlignment: TagsView.VerticalAlignment = .top
var minimumIntertagSpacing: CGFloat = 8
// MARK: - TagSizable
static func preferredSize(with contentSize: CGSize, tag: String, at index: Int) -> CGSize {
return MyTagView.preferredSize(with: contentSize, tag: tag, at: index)
}
}
3) Make an object compliant to the TagsViewDataSource
protocol. A convenient approach is to use the same TagsProvider
objet.
It can be expected the `TagsProvider` to act as data source..
public protocol TagsViewDataSource: class {
func tagsView(_ tagsView: TagsView, sizeForTagAt index: Int) -> CGSize
func tagsView(_ tagsView: TagsView, viewForTagAt index: Int) -> UIView
}
Please find an example below with the previous TagsViewModel
and MyTagView
object:
import KTTagsView
// MARK: - TagsViewDataSource
extension TagsViewModel: TagsViewDataSource {
func tagsView(_ tagsView: TagsView, sizeForTagAt index: Int) -> CGSize {
let tag = self.tags[index]
return MyTagView.preferredSize(with: tagsView.bounds.size, tag: tag, at: index)
}
func tagsView(_ tagsView: TagsView, viewForTagAt index: Int) -> UIView {
let tagView = MyTagView./*init()*/
let tag = self.tags[index]
//tagView.update(with: tag)
return tagView
}
}
4) Finally add the TagsView
to your UICollectionViewCell
, UITableViewCell
or any other parent UIView
and call the reloadData
passing your TagsProvider
and TagsViewDataSource
compliant objects.
import KTTagsView
final class TagsCollectionViewCell: UICollectionViewCell {
// MARK: Outlets
@IBOutlet weak var ibTagsView: TagsView!
// MARK: - Internal methods
func update(with viewModel: TagsViewModel) {
self.ibTagsView.reloadData(with: viewModel, dataSource: viewModel)
}
}
KTTagsView is released under the MIT license. See LICENSE for details.