-
-
Save apple-avadhesh/f3c5c186d931b1210174752784c56c06 to your computer and use it in GitHub Desktop.
Swift TagCloudCollectionView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: A UIKit based Playground for presenting user interface | |
import UIKit | |
import PlaygroundSupport | |
class EdgeInsetLabel: UILabel { | |
private let textInsets: UIEdgeInsets | |
init(inset: UIEdgeInsets) { | |
textInsets = inset | |
super.init(frame: CGRect.zero) | |
} | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect { | |
let insetRect = bounds.inset(by: textInsets) | |
let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) | |
let invertedInsets = UIEdgeInsets(top: -textInsets.top, | |
left: -textInsets.left, | |
bottom: -textInsets.bottom, | |
right: -textInsets.right) | |
return textRect.inset(by: invertedInsets) | |
} | |
override func drawText(in rect: CGRect) { | |
super.drawText(in: rect.inset(by: textInsets)) | |
} | |
} | |
class MyCell: UICollectionViewCell { | |
lazy var titleLabel: UILabel = { | |
let view = EdgeInsetLabel(inset: UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 8)) | |
view.font = .systemFont(ofSize: 16) | |
view.frame = self.contentView.frame | |
view.backgroundColor = .systemFill | |
self.contentView.addSubview(view) | |
return view | |
}() | |
func set(title: String) { | |
titleLabel.text = title | |
clipsToBounds = true | |
} | |
override func draw(_ rect: CGRect) { | |
super.draw(rect) | |
layer.cornerRadius = rect.height / 2 | |
} | |
} | |
class FlowLayout: UICollectionViewFlowLayout { | |
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { | |
guard let attributesForElementsInRect = super.layoutAttributesForElements(in: rect) else { return nil } | |
var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]() | |
// use a value to keep track of left margin | |
var leftMargin: CGFloat = 0.0; | |
var topMargin: CGFloat = 0.0; | |
for refAttributes in attributesForElementsInRect { | |
// If element on a next line | |
if topMargin != refAttributes.frame.origin.y { | |
topMargin = refAttributes.frame.origin.y | |
leftMargin = self.sectionInset.left // Start from the begining | |
} | |
// Modify frame for current refAttributes | |
var newLeftAlignedFrame = refAttributes.frame | |
newLeftAlignedFrame.origin.x = leftMargin | |
refAttributes.frame = newLeftAlignedFrame | |
// Calculate for next element in a line | |
leftMargin += refAttributes.frame.size.width + minimumInteritemSpacing | |
newAttributesForElementsInRect.append(refAttributes) | |
} | |
return newAttributesForElementsInRect | |
} | |
} | |
class MyViewController : UIViewController { | |
var data = ["Aruba ⤫", "Afghanistan ⤫", "Africa ⤫", "Angola ⤫", "Albania ⤫", "Andorra ⤫", "Andean region ⤫", "Arab World ⤫", "United Arab Emirates ⤫", "Argentina ⤫", "Armenia ⤫", "American Samoa ⤫", "Antigua and Barbuda ⤫"].shuffled() | |
override func loadView() { | |
let view = UIView() | |
view.backgroundColor = .white | |
let layout = FlowLayout() | |
layout.scrollDirection = .vertical | |
layout.minimumInteritemSpacing = 8 | |
layout.sectionInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) | |
let collection = UICollectionView(frame: .zero, collectionViewLayout: layout) | |
view.addSubview(collection) | |
collection.register(MyCell.self, forCellWithReuseIdentifier: "cell") | |
collection.backgroundColor = .systemGray4 | |
collection.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
collection.dataSource = self | |
collection.delegate = self | |
self.view = view | |
} | |
} | |
extension MyViewController: UICollectionViewDataSource { | |
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { | |
data.count | |
} | |
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | |
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) | |
if let cell = cell as? MyCell { | |
cell.set(title: data[indexPath.item]) | |
} | |
return cell | |
} | |
} | |
extension MyViewController: UICollectionViewDelegate { | |
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { | |
data.remove(at: indexPath.item) | |
collectionView.deleteItems(at: [indexPath]) | |
collectionView.collectionViewLayout.invalidateLayout() | |
} | |
} | |
extension MyViewController: UICollectionViewDelegateFlowLayout { | |
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { | |
let attributes = [ NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)] | |
var size = data[indexPath.item].size(withAttributes: attributes) | |
size.height = size.height + 16 | |
size.width = size.width + 32 | |
return size | |
} | |
} | |
// Present the view controller in the Live View window | |
PlaygroundPage.current.liveView = MyViewController() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment