Layout constraints not working properly - ios

I am having a lot of trouble getting this second custom class, which is another UICollectionView (green background) constraining to the bottom of the class above. I've tried all different sorts of constraints and constants of "0" etc. However it keeps positioning it on top of the other class. Does anyone have any ideas about what is happening?
Here is the screenshot:
class JobCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
private let cellId = "jobCellId"
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let jobLabel: UILabel = {
let label = UILabel()
label.backgroundColor = .green
label.text = "I WANT TO"
label.textColor = UIColor.rgb(red: 149, green: 149, blue: 149)
label.font = UIFont(name: "HelveticaNeue-Medium", size: 16)
label.textAlignment = .left
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let jobsCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = UIColor.red
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
func setupViews() {
backgroundColor = UIColor.clear
jobsCollectionView.dataSource = self
jobsCollectionView.delegate = self
jobsCollectionView.register(JobSingleCell.self, forCellWithReuseIdentifier: cellId)
addSubview(jobLabel)
addSubview(jobsCollectionView)
jobLabel.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true
jobLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 20).isActive = true
jobLabel.widthAnchor.constraint(equalToConstant: frame.width).isActive = true
jobLabel.heightAnchor.constraint(equalToConstant: 35).isActive = true
jobsCollectionView.topAnchor.constraint(equalTo: jobLabel.bottomAnchor, constant: 0).isActive = true
jobsCollectionView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
jobsCollectionView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
jobsCollectionView.heightAnchor.constraint(equalToConstant: frame.height).isActive = true
}
Here is the second blue cell:
class DayCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
private let dayCellId = "dayCellId"
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
let daysCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = UIColor.red
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
let dayLabel: UILabel = {
let label = UILabel()
label.backgroundColor = .green
label.text = "WHEN"
label.textColor = UIColor.rgb(red: 149, green: 149, blue: 149)
label.font = UIFont(name: "HelveticaNeue-Medium", size: 16)
label.textAlignment = .left
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
func setupViews() {
backgroundColor = UIColor.clear
addSubview(dayLabel)
dayLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
dayLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20).isActive = true
dayLabel.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
dayLabel.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true

Related

add ui label to ui imageview on collectionview

I am new to swift - I want to add a label ONTO the ui image view image in a collectionview, however i am having some issues. The text sits below the image view, how can i adjust it so it stays in the middle of the image. I want to do this in code and not use storyboards or a nib file. I believe it may be due to my frames i have set:
import UIKit
class ExploreCollectionViewCell: UICollectionViewCell {
static let identifier = "ExploreCollectionViewCell"
private let label: UILabel = {
let label = UILabel()
label.textColor = .white
label.font = UIFont(name: Settings.shared.MAIN_APP_FONT_BOLD, size: 13)
return label
}()
private let imageView: UIImageView = {
let imageView = UIImageView()
imageView.clipsToBounds = true
imageView.layer.cornerRadius = 0
imageView.contentMode = .scaleAspectFill
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(label)
contentView.addSubview(imageView)
}
required init?(coder: NSCoder) {
fatalError()
}
override func layoutSubviews() {
super.layoutSubviews()
label.frame = CGRect(x: 5, y: 0, width: contentView.frame.size.width-10, height: 50)
//imageView.frame = contentView.bounds
imageView.frame = CGRect(x: 0, y: 0, width: 250, height: 250)
}
override func prepareForReuse() {
super.prepareForReuse()
imageView.image = nil
}
func configure(with urlString: String, label: String) {
guard let url = URL(string: urlString) else {
return
}
let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
guard let data = data, error == nil else {
return
}
DispatchQueue.main.async {
self?.label.text = label
let image = UIImage(data: data)
self?.imageView.image = image
}
}
task.resume()
}
}
First, add the imageView before adding the label, so that it will be shown behind the label:
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(imageView) // behind
contentView.addSubview(label) // front
}
Second, it would be easier to use auto layout:
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.widthAnchor.constraint(equalToConstant: 250).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 250).isActive = true
label.translatesAutoresizingMaskIntoConstraints = false
label.centerYAnchor.constraint(equalTo: imageView.centerYAnchor).isActive = true
label.widthAnchor.constraint(equalTo: imageView.widthAnchor).isActive = true
private let label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = .white
label.font = UIFont(name: Settings.shared.MAIN_APP_FONT_BOLD, size: 13)
return label
}()
private let imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.clipsToBounds = true
imageView.layer.cornerRadius = 0
imageView.contentMode = .scaleAspectFill
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(label)
contentView.addSubview(imageView)
imageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0).isActive = true
imageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0).isActive = true
imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true
imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true
label.heightAnchor.constraint(equalToConstant: 50).isActive = true
label.centerYAnchor.constraint(contentView.centerYAnchor).isActive = true
label.centerXAnchor.constraint(contentView.centerXAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 5).isActive = true
label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true
}
required init?(coder: NSCoder) {
fatalError()
}

Swift: UIStackView of UIControls with selector method that doesn't fire

Introduction
I'm creating an app which uses a custom view in which I have a UIStackView to sort out 5 UIControls. When a user taps one of the UIControls an underscore line gets animated, sliding under the tapped UIControl.
However, for some reason the method/selector for these UIControls no longer gets called. I believe this has to do with that I updated my Mac to the macOS (and Xcode) update released this week (wk.44). (updated from swift 4.2 to swift 4.2.1). Before the updated this animation and selector worked perfectly. But I'm not sure. And I'm now completely stuck on what I'm doing wrong.
Context
I created a playground and scaled down everything as much as I could and the issue persists.
I have tried to define the UIStackView in the global scope of my SetupView class but it doesn't change anything. So I believe it is not an issue of the stackView or its subviews being deallocated?
Below I've provided my UIControl subclass and my SetupView (UIView subclass) that I use. I've created a playground so you may copy paste in Xcode playground to test if you want.
Question
Why doesn't the method goalViewControlTapped(_ sender: SetupViewControl) get called?
Code
import UIKit
import PlaygroundSupport
class SetupViewControl: UIControl {
let titleLabel : UILabel = {
let lbl = UILabel()
lbl.font = UIFont(name: "Futura", size: 14)
lbl.textColor = .white
lbl.backgroundColor = .clear
lbl.textAlignment = .center
lbl.translatesAutoresizingMaskIntoConstraints = false
return lbl
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupLabel()
layer.cornerRadius = 5
}
fileprivate func setupLabel() {
addSubview(titleLabel)
titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 5).isActive = true
titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -5).isActive = true
titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var isHighlighted: Bool {
didSet {
UIView.animate(withDuration: 0.12) {
self.backgroundColor = self.isHighlighted ? UIColor.lightGray : UIColor.clear
}
}
}
}
class SetupView: UIView {
let dataModel : [String] = ["2 weeks", "1 month", "2 months", "6 months", "1 year"]
var selectionLineCenterX : NSLayoutConstraint!
let selectionLine = UIView()
let labelZero = SetupViewControl()
let labelOne = SetupViewControl()
let labelTwo = SetupViewControl()
let labelThree = SetupViewControl()
let labelFour = SetupViewControl()
let labelFive = SetupViewControl()
lazy var controlArray = [self.labelZero, self.labelOne, self.labelTwo, self.labelThree, self.labelFour, self.labelFive]
init(frame: CGRect, color: UIColor) {
super.init(frame: frame)
self.backgroundColor = color
setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func setupView() {
layer.cornerRadius = 0
layer.borderColor = UIColor.black.cgColor
layer.borderWidth = 1
setupLabelText()
setupControlsInStackView()
}
fileprivate func setupLabelText() {
for num in 0...(dataModel.count - 1) {
controlArray[num].titleLabel.text = dataModel[num]
}
}
// let stackView = UIStackView(frame: .zero) I have tried to declare the stackView here but it doesn't fix my issue.
func setupControlsInStackView() {
var stackViewArray = [SetupViewControl]()
for num in 0...(dataModel.count - 1) {
controlArray[num].isUserInteractionEnabled = true
controlArray[num].addTarget(self, action: #selector(goalViewControlTapped(_:)), for: .touchUpInside)
stackViewArray.append(controlArray[num])
}
let stackView = UIStackView(arrangedSubviews: stackViewArray)
stackView.alignment = .fill
stackView.distribution = .fillEqually
stackView.axis = .horizontal
stackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(stackView)
stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8).isActive = true
stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8).isActive = true
stackView.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true
addSubview(selectionLine)
selectionLine.backgroundColor = .white
selectionLine.translatesAutoresizingMaskIntoConstraints = false
selectionLine.heightAnchor.constraint(equalToConstant: 1).isActive = true
selectionLine.topAnchor.constraint(equalTo: stackView.bottomAnchor).isActive = true
selectionLine.widthAnchor.constraint(equalToConstant: 50).isActive = true
selectionLineCenterX = selectionLine.centerXAnchor.constraint(equalTo: leadingAnchor, constant: -100)
selectionLineCenterX.isActive = true
}
#objc fileprivate func goalViewControlTapped(_ sender: SetupViewControl) {
print("This is not getting printed!!!")
selectionLineCenterX.isActive = false
selectionLineCenterX = selectionLine.centerXAnchor.constraint(equalTo: sender.centerXAnchor)
selectionLineCenterX.isActive = true
UIView.animate(withDuration: 0.25, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.5, options: .curveEaseIn, animations: {
self.layoutIfNeeded()
}, completion: nil)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let testView = SetupView(frame: .zero, color: UIColor.blue)
view.addSubview(testView)
testView.translatesAutoresizingMaskIntoConstraints = false
testView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
testView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
testView.heightAnchor.constraint(equalToConstant: 100).isActive = true
testView.widthAnchor.constraint(equalToConstant: 365).isActive = true
}
}
// For live view in playground
let vc = ViewController()
vc.preferredContentSize = CGSize(width: 375, height: 812)
PlaygroundPage.current.liveView = vc
Thanks for reading my question.
Does your UIStackView show as having an ambiguous layout when you open the view debugger? If so, that may be causing the internal views to not receive the touch events.
You can provide UIStackView with either:
x and y constraints only
or
x, y, width and height.
In the above case the height constraint is missing.

Swift: How to programmatically create reusable views?

Let's say I am describing my own UIView, let's call it a HeaderView. I want the HeaderView to have the exact same properties, but only differ in label text. Here is how I currently have it:
private let headerView: UIView = {
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
let view = UIView()
view.backgroundColor = .white
view.heightAnchor.constraint(equalToConstant: 65).isActive = true
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 30)
label.textAlignment = .left
label.textColor = .black
label.text = "Search"
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8).isActive = true
label.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 5).isActive = true
return view
}()
How I'd use it:
view.addSubview(headerView)
headerView.translatesAutoresizingMaskIntoConstraints = false
headerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
headerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
What if I want 3 of these header views with varying text? How would I make it into a reusable programmatic view?
You can create a subclass of UIView and reuse it anywhere
class HeaderView: UIView {
let innerview = UIView()
let innerlabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
sharedLayout()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sharedLayout()
}
private func sharedLayout() {
self.addSubview(innerview)
self.innerView.backgroundColor = UIColor.red
innerview.translatesAutoresizingMaskIntoConstraints = false
innerview.trailingAnchor.constraint(equalTo:self.trailingAnchor).isActive = true
innerview.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
innerview.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
innerview.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
// configure other items here
}
}
Instead of a variable you could have a function:
func buildHeaderView(withText text: String) -> UIView {
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
let view = UIView()
view.backgroundColor = .white
view.heightAnchor.constraint(equalToConstant: 65).isActive = true
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 30)
label.textAlignment = .left
label.textColor = .black
label.text = text
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8).isActive = true
label.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 5).isActive = true
return view
}
Now you could use this function like:
let searchHeaderView = buildHeaderView(withText: "Search")
view.addSubview(searchHeaderView)
let otherView = buildHeaderView(withText: "Other")

Auto Layout using layout anchors programmatically not working

I am trying to add a stack view containing a UILabel at the top and a UICollectionView underneath. I am trying to constrain the stack view so that it takes up the full view, by anchoring it to all sides. When I run the app the UILabel appears and a slice of the collection view appears. The collection view says its width and height are both zero. Any help would be appreciated, thank you.
var collectionView: UICollectionView!
var titleLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.translatesAutoresizingMaskIntoConstraints = false
let margins = self.view.layoutMarginsGuide
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
layout.itemSize = CGSize(width: self.collectionView.frame.width / 4, height: self.collectionView.frame.width / 4)
layout.minimumInteritemSpacing = self.collectionView.frame.width / 15
layout.minimumLineSpacing = self.collectionView.frame.width / 5
collectionView.backgroundColor = UIColor.black
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
titleLabel = UILabel()
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.textAlignment = .center
titleLabel.numberOfLines = 1
titleLabel.font = UIFont.systemFont(ofSize: 22)
titleLabel.backgroundColor = UIColor.lightGray
titleLabel.text = "Challenges"
titleLabel.textColor = UIColor.red
let stackView = UIStackView(arrangedSubviews: [titleLabel, collectionView])
stackView.backgroundColor = UIColor.white
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.alignment = .fill
stackView.spacing = 5
self.view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
//stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
//stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 1.0).isActive = true
}
UPDATE:
I took my code and ran it in a new single view application and it worked as expected. Because of this I think it is worth it to mention that I am trying to incorporate this into a sprite kit game and I present the view controller by doing this:
let root = self.view?.window?.rootViewController
var viewC = SelectionCollectionViewController()
root?.present(viewC, animated: false, completion: nil)
Are there special steps I need to take because this is done with sprite kit?
I believe below screen shot is the expected output.
You might not need UIStackView , You can directly add it to self.view.
Once added to self.view, you can set up constraints. You can print the item Size in viewDidLayoutSubviews
class ViewController: UIViewController {
var collectionView: UICollectionView!
var titleLabel: UILabel!
let collectionCellIdentifier:String = "collectionCellId"
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: 20, left: 10, bottom: 10, right: 10)
collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(UICollectionViewCell.classForCoder(), forCellWithReuseIdentifier: collectionCellIdentifier)
collectionView.backgroundColor = UIColor.black
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
titleLabel = UILabel()
titleLabel.textAlignment = .center
titleLabel.numberOfLines = 1
titleLabel.font = UIFont.systemFont(ofSize: 22)
titleLabel.backgroundColor = UIColor.lightGray
titleLabel.text = "Challenges"
titleLabel.textColor = UIColor.red
titleLabel.translatesAutoresizingMaskIntoConstraints = false
collectionView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(titleLabel)
self.view.addSubview(collectionView)
setUpConstraints()
}
func setUpConstraints(){
self.view.addConstraint(NSLayoutConstraint(item: self.titleLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier:0, constant:50.0 ))
titleLabel.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
titleLabel.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
titleLabel.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
collectionView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor).isActive = true
collectionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
collectionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let flowLayout = (collectionView.collectionViewLayout as! UICollectionViewFlowLayout)
flowLayout.itemSize = CGSize(width: collectionView.frame.width / 4.0 , height: collectionView.frame.width / 4.0)
flowLayout.minimumInteritemSpacing = self.collectionView.frame.width / 15.0
flowLayout.minimumLineSpacing = self.collectionView.frame.width / 5.0
}
}
extension ViewController:UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: collectionCellIdentifier, for: indexPath)
cell.backgroundColor = UIColor.gray
return cell
}
}
I think you need to know what happen in these functions:
viewDidLoad
viewWillAppear
viewWillLayoutSubviews
viewDidLayoutSubviews
viewDidAppear
if you use autoLayout, when in viewDidLoad(), the frame is not confirmed, because the view will make an auto adjustment when in viewWillLayoutSubviews() and viewDidLayoutSubviews(), so I suggest you make these code in viewDidAppear(), and then you may see what you want!
Furthermore, if you use storyboard or nib, you need to do these in awakeFromNib()

How can I center UIView in a custom control?

I'm working on a exercise to create a custom control of anything. My idea is to have a UIView in the middle of the screen and a UILabel below it. When you tap on the view a random color will appear with the label changing to its hex value. When trying to create this custom control I'm having a problem trying to center the UIView programmatically. I get to an issue at `colorBox.center~
import UIKit
#IBDesignable
class Color: UIView {
private lazy var label : UILabel = {
let label = UILabel()
label.backgroundColor = UIColor.clear
label.translatesAutoresizingMaskIntoConstraints = false
label.heightAnchor.constraint(equalToConstant: 25.0).isActive = true
label.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
label.font = .systemFont(ofSize: 15.0, weight: UIFontWeightRegular)
return label
}()
private lazy var colorGen : UIView = {
let colorBox = UIView()
colorBox.backgroundColor = UIColor.black
colorBox.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
colorBox.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
colorBox.centerXAnchor.constraint(equalTo: colorBox.frame.size.width /2)
}()
override init (frame: CGRect) {
super.init(frame:frame)
setUpLabel()
setUpView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUpLabel()
setUpView()
}
I've tried the answers about using self.view but it doesn't work for me so I'm a bit lost.
You're close, but you need to add the label and the view so you can then constrain them relative to the superview...
#IBDesignable
class ColorView: UIView {
private lazy var colorLabel : UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.backgroundColor = UIColor.clear
label.heightAnchor.constraint(equalToConstant: 25.0).isActive = true
label.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
label.font = .systemFont(ofSize: 15.0, weight: UIFontWeightRegular)
return label
}()
private lazy var colorGen : UIView = {
let colorBox = UIView()
colorBox.translatesAutoresizingMaskIntoConstraints = false
colorBox.backgroundColor = UIColor.cyan
colorBox.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
colorBox.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
return colorBox
}()
override init (frame: CGRect) {
super.init(frame:frame)
commonSetup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonSetup()
}
func commonSetup() -> Void {
self.addSubview(colorGen)
self.addSubview(colorLabel)
colorGen.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0.0).isActive = true
colorGen.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0.0).isActive = true
colorGen.topAnchor.constraint(equalTo: self.topAnchor, constant: 0.0).isActive = true
colorLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0.0).isActive = true
colorLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0.0).isActive = true
colorLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0.0).isActive = true
colorLabel.topAnchor.constraint(equalTo: colorGen.bottomAnchor, constant: 0.0).isActive = true
colorLabel.text = "the label"
}
}

Resources