How do I add subviews to a custom UICollectionViewCell - ios

I have a custom UICollectionViewCell class where I want to add subviews.
My cell class: The SetUpView() method will add all the subvies I need.
import Foundation
import UIKit
class RecipeCell: UICollectionViewCell {
var RecipeImg: UIImage!
var StarRatingImg: UIImage!
var RecipeTitleText = ""
var RecipeTextDescription = ""
var View: UIView!
var ImageContainer: UIImageView!
var FavIcon: UIImageView!
var StarRatingContainer: UIImageView!
var KCAL: UILabel!
var RecipeTitle: UITextView!
var RecipeText: UITextView!
func SetUpView()
{
//DropDown!.backgroundColor = UIColor.blueColor()
self.translatesAutoresizingMaskIntoConstraints = false
//View for recipe
View = UIView(frame: CGRectMake(0, 0, self.frame.width, self.frame.height))
View.backgroundColor = UIColor.whiteColor()
//Recipe image
ImageContainer = UIImageView(frame: CGRectMake(0, 0, View.frame.width, View.frame.height/2))
ImageContainer.image = RecipeImg
ImageContainer.contentMode = .ScaleToFill
//Recipe favorit icon
FavIcon = UIImageView(frame: CGRectMake(ImageContainer.frame.width - 35, 5, 30, 30))
FavIcon.image = UIImage(named: "LikeHeart")
//Star rating image
StarRatingContainer = UIImageView(frame: CGRectMake(10, ImageContainer.frame.height + 5, ImageContainer.frame.width - 20, (View.frame.height/2) * (1/5)))
StarRatingContainer.image = StarRatingImg
StarRatingContainer.contentMode = .ScaleAspectFit
//RecipeTitle container
RecipeTitle = UITextView(frame: CGRectMake(10, StarRatingContainer.frame.height + ImageContainer.frame.height + 10, View.frame.width - 20, 30))
RecipeTitle.font = UIFont(name: "OpenSans-Semibold", size: 12)
//RecipeTitle.backgroundColor = UIColor.redColor()
RecipeTitle.editable = false
RecipeTitle.text = RecipeTitleText
RecipeTitle.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
//RecipeText container
RecipeText = UITextView(frame: CGRectMake(10, StarRatingContainer.frame.height + ImageContainer.frame.height + RecipeTitle.frame.height + 15, View.frame.width - 20, 50))
RecipeText.font = UIFont(name: "OpenSans", size: 12)
//RecipeText.backgroundColor = UIColor.grayColor()
RecipeText.editable = false
RecipeText.text = RecipeTextDescription
RecipeText.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
//KCAL label
KCAL = UILabel(frame: CGRectMake(15, StarRatingContainer.frame.height + ImageContainer.frame.height + RecipeTitle.frame.height + RecipeText.frame.height + 20, 200, 20))
KCAL.text = "420 KCAL. PER. PORTION"
KCAL.font = UIFont(name: "OpenSans-Bold", size: 10)
KCAL.textColor = UIColor(CGColor: "#dc994a".CGColor)
//Adding the views
self.addSubview(View)
View.addSubview(ImageContainer)
View.addSubview(KCAL)
View.addSubview(StarRatingContainer)
View.addSubview(RecipeTitle)
View.addSubview(RecipeText)
ImageContainer.addSubview(FavIcon)
View.bringSubviewToFront(ImageContainer)
}
}
I have a UICollectionView which uses the custom cell class.
I create my UICollectionView in viewDidLoad()
// Create Collection view
layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
layout.itemSize = CGSize(width: screenWidth/MenuViewConst - 1, height: screenWidth - 1)
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
collectionView = UICollectionView(frame: CGRect(x: 0, y: 105, width: self.view.frame.width, height: self.view.frame.height - 150), collectionViewLayout: layout)
collectionView?.tag = 5
collectionView!.dataSource = self
collectionView!.delegate = self
collectionView!.registerClass(RecipeCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
collectionView!.backgroundColor = UIColor.lightGrayColor()
collectionView!.contentInset.top = 0
In cellForItemAtIndexPath delegate I set up the UICollectionView to use my custom cell class. But I can't call the SetUpView() method from my custom cell class here, because that will just keep adding subviews on subviews. I can't figure out how to add the subviews to the UICollectionViewCell before entering the delegate. Hope you guys can help - Thank you
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as! RecipeCell
let recipe = self.RecipeArr[indexPath.row]
cell.backgroundColor = UIColor.grayColor()
cell.layer.borderColor = UIColor.whiteColor().CGColor
cell.layer.borderWidth = 0.5
cell.RecipeImg = UIImage(named: "Burger")
cell.StarRatingImg = UIImage(named: "StarRating")
cell.RecipeTitleText = recipe["name"].string!
cell.RecipeTextDescription = recipe["instruction"].string!
//BAD IDEA!
//cell.SetUpView()
print("new cell")
return cell
}

You need to use init(frame: CGRect) inherited function in the UICollectionViewCell .
class RecipeCell: UICollectionViewCell {
var imageView : UIImageView?
override init(frame: CGRect) {
super.init(frame: frame)
//initialize all your subviews.
imageView = UIImageView()
}
}
also don't forget to register your custom class in the viewDidLoad function
collectionView!.registerClass(RecipeCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
and your collectionview delegate would be like this
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as! RecipeCell
cell.imageView.image = UIImage(named:"yourImage.png")
}

Related

UICollectionView's background is a screenshot of the initial position of the scrollview?

This seems like a weird bug and I have adapted the code to see the bug better. By default the background color of my UICollectionView seems to be .systemBackground, but when I set it to .clear, instead of having a clear background, I have a "ghost" of the starting position of the first items in the scroll as a abckground. What could be happening?
The functions of the UICollectionView protocol:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 30
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LineCell", for: indexPath) as! LineCell
cell.changeSize(indexPath.row)
cell.text.text = String(indexPath.row)
return cell
}
How I'm adding the view:
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.estimatedItemSize = CGSize(width: 50, height: 80)
numberPicker = UICollectionView(frame: .zero, collectionViewLayout: layout)
secondsControlHolder.addSubview(numberPicker!)
numberPicker?.delegate = delegate
numberPicker?.dataSource = delegate
numberPicker?.register(LineCell.self, forCellWithReuseIdentifier: "LineCell")
numberPicker?.translatesAutoresizingMaskIntoConstraints = false
numberPicker?.heightAnchor.constraint(equalToConstant: 120).isActive = true
numberPicker?.bottomAnchor.constraint(equalTo: secondsControlHolder.bottomAnchor).isActive = true
numberPicker?.leadingAnchor.constraint(equalTo: secondsControlHolder.leadingAnchor).isActive = true
numberPicker?.trailingAnchor.constraint(equalTo: secondsControlHolder.trailingAnchor).isActive = true
numberPicker?.backgroundColor = .clear
numberPicker?.showsVerticalScrollIndicator = false
numberPicker?.showsHorizontalScrollIndicator = false
numberPicker?.isPagingEnabled = false
numberPicker?.contentInset = UIEdgeInsets(top: 0, left: (delegate.view.frame.size.width)/2, bottom: 0, right: (delegate.view.frame.size.width)/2)
let arrow = UIView()
let arrowTriangle = UIImageView(image: UIImage(systemName: "arrowtriangle.up.fill"))
secondsControlHolder.addSubview(arrow)
secondsControlHolder.addSubview(arrowTriangle)
arrow.translatesAutoresizingMaskIntoConstraints = false
arrow.bottomAnchor.constraint(equalTo: secondsControlHolder.bottomAnchor, constant: -10).isActive = true
arrow.centerXAnchor.constraint(equalTo: secondsControlHolder.centerXAnchor).isActive = true
arrow.heightAnchor.constraint(equalToConstant: 100).isActive = true
arrow.backgroundColor = .label
arrow.widthAnchor.constraint(equalToConstant: 5).isActive = true
arrow.isUserInteractionEnabled = false
arrowTriangle.translatesAutoresizingMaskIntoConstraints = false
arrowTriangle.centerXAnchor.constraint(equalTo: arrow.centerXAnchor).isActive = true
arrowTriangle.topAnchor.constraint(equalTo: secondsControlHolder.bottomAnchor, constant: -130).isActive = true
arrowTriangle.tintColor = .label
arrowTriangle.heightAnchor.constraint(equalToConstant: 23).isActive = true
arrowTriangle.widthAnchor.constraint(equalToConstant: 30).isActive = true
The LineCell class:
import UIKit
class LineCell: UICollectionViewCell {
let lineHolder = UIView()
let text = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
text.text = "test"
text.textColor = .white
lineHolder.translatesAutoresizingMaskIntoConstraints = false
lineHolder.addSubview(text)
text.translatesAutoresizingMaskIntoConstraints = false
text.topAnchor.constraint(equalTo: lineHolder.topAnchor).isActive = true
text.bottomAnchor.constraint(equalTo: lineHolder.bottomAnchor).isActive = true
text.leadingAnchor.constraint(equalTo: lineHolder.leadingAnchor).isActive = true
text.trailingAnchor.constraint(equalTo: lineHolder.trailingAnchor).isActive = true
addSubview(lineHolder)
// layer.backgroundColor = CGColor(red: 100, green: 100, blue: 100, alpha: 1)
// setupLineHolder()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupLineHolder(){
lineHolder.frame = CGRect(x: 0, y: 0, width: 1, height: 80)
lineHolder.backgroundColor = .label
// setupLine()
}
func changeSize(_ index: Int){
if index % 5 == 0 {
lineHolder.frame = CGRect(x: 0, y: 0, width: 50, height: 80)
lineHolder.backgroundColor = .label
}else{
lineHolder.frame = CGRect(x: 0, y: 15, width: 50, height: 50)
lineHolder.backgroundColor = .label.withAlphaComponent(0.7)
}
}
}
Turns out I was calling setupControlsArea() twice. It wasn't just the UICollectionView that was duplicated, but the whole controls area view.

UIActivityIndicatorView disappears in CollectionView Footer

I have a collectionView with only 1 section in my app which download data from API. I have a pagination and I am trying to add a loading footer in my collectionView. The header appears normally. I have in this footer cell an UIActivityIndicatorView and a UILabel. When the first at a limit is triggered, the 2 elements are present in the cell but when the second limit is triggered, the UIActivityIndicatorView is absent.
Have you an idea for that.
The code of the cell (BaseCell is just a class to avoid tapping the init and required init each time):
class loadingCell: BaseCell {
override func setupViews() {
super.setupViews()
backgroundColor = .yellow
let activity = UIActivityIndicatorView()
activity.backgroundColor = .red
activity.startAnimating()
activity.frame = CGRect(x: 10, y: 20, width: 20, height: 20)
let label = UILabel()
label.text = "hello"
label.frame = CGRect(x: 100, y: 20, width: 40, height: 20)
label.backgroundColor = .green
addSubview(activity)
addSubview(label)
}
}
The collection delegate methods :
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: SCREENW, height: 50)
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionElementKindSectionFooter {
let loadingFooterView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionFooter, withReuseIdentifier: loadingCell, for: indexPath)
return loadingFooterView
}
return UICollectionReusableView()
}
The cell is well registered.
What happens when first limit is triggered:
And with the second:
Based on #MaksymMusiienko comment, I have tried this which do the job to reset the animation of the spinner.
class loadingCell: BaseCell {
let activitySpinner: UIActivityIndicatorView = {
let spinner = UIActivityIndicatorView()
spinner.backgroundColor = .red
spinner.startAnimating()
spinner.frame = CGRect(x: 10, y: 20, width: 20, height: 20)
return spinner
}()
override func setupViews() {
super.setupViews()
backgroundColor = .yellow
let label = UILabel()
label.text = "hello"
label.frame = CGRect(x: 100, y: 20, width: 40, height: 20)
label.backgroundColor = .green
addSubview(activitySpinner)
addSubview(label)
}
override func prepareForReuse() {
super.prepareForReuse()
activitySpinner.startAnimating()
}
}

UICollectionViewCell with AutoLayout not working in iOS 10

I'm trying to create a dynamic UICollectionView whose cells auto-resize based on the text inside it. But for some reasons, my custom UICollectionViewCell won't expand to the full width. I am using SnapKit as AutoLayout and all my views are code-based; no xib or storyboard. Here's a debug view of what I got at the moment:
I want the cell to expand full width and the height to fit whatever the content is. Here's a snippet on my UICollectionViewController
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Home"
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: view.frame.width, height: view.frame.height)
layout.scrollDirection = .vertical
layout.estimatedItemSize = CGSize(width: 375, height: 250)
collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height), collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.backgroundColor = UIColor(red: 245/255, green: 245/255, blue: 245/255, alpha: 1)
collectionView.register(HomeCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
self.view.addSubview(collectionView)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
// Configure the cell
if let c = cell as? HomeCollectionViewCell {
c.contentView.frame = c.bounds
c.contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
configureCell(c, indexPath: indexPath)
}
return cell
}
func configureCell(_ cell: HomeCollectionViewCell, indexPath: IndexPath) {
cell.setText(withTitle: items[(indexPath as NSIndexPath).section].title)
}
And here's a snippet of my custom UICollectionViewCell
override init(frame: CGRect) {
super.init(frame: frame)
self.contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
self.contentView.translatesAutoresizingMaskIntoConstraints = true
self.contentView.bounds = CGRect(x: 0, y: 0, width: 99999, height: 99999)
createTitle()
}
private func createTitle() {
titleView = TTTAttributedLabel(frame: CGRect(x: 0, y: 0, width: contentView.frame.width, height: 56))
titleView.tag = 1
titleView.numberOfLines = 2
titleView.delegate = self
titleView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(titleView)
titleView.snp_updateConstraints(closure: {
make in
make.leading.trailing.equalTo(contentView).offset(10)
make.top.equalTo(contentView).offset(10)
make.bottom.equalTo(contentView).offset(-10)
})
}
func setText(withTitle title:String, paragraph: String, image: String) {
let titleAttributed = AttributedString(string: title, attributes: titleStringAttr)
titleView.attributedText = titleAttributed
titleView.sizeToFit()
}
I've spent 3 days just working on this on and on.. Any advice appreciated!
Well it's not really a solution, but the TTTAttributedLabel does some black magic that causes the AutoLayout not to work. So for me, I changed the TTTAttributedLabel to UILabel and it works fine.
FYI I posted similar question on SnapKit Github issues; credits to robertjpayne there for the hint (https://github.com/SnapKit/SnapKit/issues/261)

Create Custom Dynamic Prototype Cells programmatically

I am having an issue trying to create Dynamic Prototype Cells programmatically. This is my first time trying this approach. I have always created them through storyboard.
I have my ViewController.swift file which contains the following
var noteListTableView: UITableView = UITableView()
noteListTableView.frame.origin.x = 0.0
noteListTableView.frame.origin.y = kNAV_BAR_HEIGHT
noteListTableView.frame.size.width = kDEVICE_WIDTH
noteListTableView.frame.size.height = kDEVICE_HEIGHT - kNAV_BAR_HEIGHT
noteListTableView.dataSource = self
noteListTableView.delegate = self
self.view.addSubview(noteListTableView)
Also in the file, I have included the appropriate TableView delegate and Data source functions
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return GlobalDataController.notesDB.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var aNote: NoteItem = GlobalDataController.notesDB[indexPath.row] as NoteItem
if var cell: NoteListTVCell = noteListTableView.dequeueReusableCellWithIdentifier(kReuseCellNoteList) as? NoteListTVCell {
cell.noteTitle.text = "Title"
cell.noteContentSummary.text = "Content Summary"
cell.noteDate.text = "May 20"
return cell
}
else{
var cell: NoteListTVCell = NoteListTVCell(style: UITableViewCellStyle.Default, reuseIdentifier: kReuseCellNoteList)
cell.noteTitle.text = "Title"
cell.noteContentSummary.text = "Content Summary"
cell.noteDate.text = "May 20"
return cell
}
}
(1) The IF-STATEMENT always seems to fail, that is why I added the else statement as per some example I found online for Obj-C.
(2) When the ELSE is triggered, the program always crashes trying to assign the cell.* values, saying it encountered a nil value.
EDIT: NoteListTVCell
class NoteListTVCell: UITableViewCell {
var noteTitle: UILabel!
var noteContentSummary: UILabel!
var noteDate: UILabel!
var cellMargin: CGFloat = kPadding * 3
override func awakeFromNib() {
super.awakeFromNib()
noteTitle = UILabel(frame: CGRect(x: cellMargin, y: kPadding, width: kDEVICE_WIDTH - cellMargin - kPadding, height: 30.0))
noteTitle.backgroundColor = kColorTransparent
noteTitle.font = UIFont(name: kFont02, size: 20.0)
noteTitle.textColor = Scripts.hexColor(0x000000, alpha: 0.8)
noteTitle.text = "Title"
self.addSubview(noteTitle)
/* Note Content Summary
-----------------------------------------------------------------------------------------*/
var noteContentSummaryY: CGFloat = noteTitle.frame.origin.y + noteTitle.frame.size.height
noteContentSummary = UILabel(frame: CGRect(x: cellMargin, y: noteContentSummaryY, width: kDEVICE_WIDTH - cellMargin - kPadding, height: 20.0))
noteContentSummary.backgroundColor = kColorTransparent
noteContentSummary.font = UIFont(name: kFont02, size: 14.0)
noteContentSummary.textColor = Scripts.hexColor(0x000000, alpha: 0.4)
noteContentSummary.text = "This is a summary..."
self.addSubview(noteContentSummary)
/* Note Date
-----------------------------------------------------------------------------------------*/
noteDate = UILabel(frame: CGRect(x: kDEVICE_WIDTH - 100.0 - kPaddingx2, y: kPadding, width: 100.0, height: 20.0))
noteDate.backgroundColor = kColorTransparent
noteDate.font = UIFont(name: kFont02, size: 10.0)
noteDate.textColor = Scripts.hexColor(kColorThemeBlue, alpha: 1.0)
noteDate.textAlignment = NSTextAlignment.Right
noteDate.text = "May 8, 2:14 AM"
self.addSubview(noteDate)
}
}
You haven't override the init method in your custom cell, but anyway it will call super init method, if you don't provide. Put your cell initialisation code in init method instead of awakeFromNib method.
Try this below.
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//Do your cell set up
noteTitle = UILabel(frame: CGRect(x: cellMargin, y: kPadding, width: kDEVICE_WIDTH - cellMargin - kPadding, height: 30.0))
noteTitle.backgroundColor = kColorTransparent
noteTitle.font = UIFont(name: kFont02, size: 20.0)
noteTitle.textColor = Scripts.hexColor(0x000000, alpha: 0.8)
noteTitle.text = "Title"
self.addSubview(noteTitle)
/* Note Content Summary
-----------------------------------------------------------------------------------------*/
var noteContentSummaryY: CGFloat = noteTitle.frame.origin.y + noteTitle.frame.size.height
noteContentSummary = UILabel(frame: CGRect(x: cellMargin, y: noteContentSummaryY, width: kDEVICE_WIDTH - cellMargin - kPadding, height: 20.0))
noteContentSummary.backgroundColor = kColorTransparent
noteContentSummary.font = UIFont(name: kFont02, size: 14.0)
noteContentSummary.textColor = Scripts.hexColor(0x000000, alpha: 0.4)
noteContentSummary.text = "This is a summary..."
self.addSubview(noteContentSummary)
/* Note Date
-----------------------------------------------------------------------------------------*/
noteDate = UILabel(frame: CGRect(x: kDEVICE_WIDTH - 100.0 - kPaddingx2, y: kPadding, width: 100.0, height: 20.0))
noteDate.backgroundColor = kColorTransparent
noteDate.font = UIFont(name: kFont02, size: 10.0)
noteDate.textColor = Scripts.hexColor(kColorThemeBlue, alpha: 1.0)
noteDate.textAlignment = NSTextAlignment.Right
noteDate.text = "May 8, 2:14 AM"
self.addSubview(noteDate)
}
Do this in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
noteListTableView = UITableView(frame: self.view.frame, style: UITableViewStyle.Plain)
noteListTableView.dataSource = self
noteListTableView.delegate = self
self.view.addSubview(noteListTableView)
noteListTableView.registerClass(NoteListTVCellTableViewCell.self, forCellReuseIdentifier: kReuseCellNoteList)
// Do any additional setup after loading the view, typically from a nib.
}
You need to register your custom tableViewCell class in viewDidLoad:
notelistTableView.registerClass(NoteListTVCell.self, forCellReuseIdentifier: kReuseCellNoteList)
Documentation
When designing the prototype in InterfaceBuilder this is done automatically. It is required when you design your cell in code.

Swift iOS - Tag collection view

I'm writing my first iOS app and I wanna just answer what is the best-known solution to make this? It's simple tag collection. I have already looked over the Internet but I have found nothing. I think the best way is to make my own structure of buttons maybe?
Here is what I want to achieve:
sometimes you need do it yourself:
import UIKit
import PlaygroundSupport
class TagsView: UIView {
// MARK: - Properties
var offset: CGFloat = 5
// MARK: - Public functions
func create(cloud tags: [UIButton]) {
var x = offset
var y = offset
for (index, tag) in tags.enumerated() {
tag.frame = CGRect(x: x, y: y, width: tag.frame.width, height: tag.frame.height)
x += tag.frame.width + offset
let nextTag = index <= tags.count - 2 ? tags[index + 1] : tags[index]
let nextTagWidth = nextTag.frame.width + offset
if x + nextTagWidth > frame.width {
x = offset
y += tag.frame.height + offset
}
addSubview(tag)
}
}
}
private func button(with title: String) -> UIButton {
let font = UIFont.preferredFont(forTextStyle: .headline)
let attributes: [NSAttributedString.Key: Any] = [.font: font]
let size = title.size(withAttributes: attributes)
let button = UIButton(type: .custom)
button.setTitle(title, for: .normal)
button.titleLabel?.font = font
button.setTitleColor(.darkGray, for: .normal)
button.layer.borderWidth = 1.0
button.layer.cornerRadius = size.height / 2
button.layer.borderColor = UIColor.darkGray.cgColor
button.frame = CGRect(x: 0.0, y: 0.0, width: size.width + 10.0, height: size.height + 10.0)
button.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: 5.0, bottom: 0.0, right: 5.0)
return button
}
let titles = ["Freedom", "God", "Happiness", "Imagination", "Intelligence", "Other"]
let tags = titles.map { button(with: $0) }
let frame = CGRect(x: 0, y: 0, width: 260, height: 200)
let tagsView = TagsView(frame: frame)
tagsView.backgroundColor = .white
tagsView.create(cloud: tags)
PlaygroundPage.current.liveView = tagsView
PlaygroundPage.current.needsIndefiniteExecution = true
I resolve this problem, using collection view.
class FilterController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
#IBOutlet var collectionView: UICollectionView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 150, left: 10, bottom: 150, right: 10)
// layout.itemSize = CGSize(width: 90, height: 45)
layout.itemSize = CGSizeFromString("Aloha")
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView!.dataSource = self
collectionView!.delegate = self
collectionView!.registerClass(TagCell.self, forCellWithReuseIdentifier: "TagCell")
collectionView!.backgroundColor = UIColor.whiteColor()
self.view.addSubview(collectionView!)
}
Just dynamically add buttons to the superView, and change the background as per your requirement.

Resources