Gradient color for text to UITextView - swift

I need to set gradient color with to colors into UITextView with white background color like in instagram stories. Example below:

Ignore the constraints set in the following code, but the concept should go like this:
containerView = GradientView.init()
self.view.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
containerView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
containerView.widthAnchor.constraint(equalToConstant: 220).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 50).isActive = true
containerView.backgroundColor = .white
textView = UITextView()
containerView.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
textView.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant: 0).isActive = true
textView.rightAnchor.constraint(equalTo: containerView.rightAnchor, constant: 0).isActive = true
textView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 0).isActive = true
textView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0).isActive = true
textView.text = "#SomeValue"
textView.font = UIFont.systemFont(ofSize: 22, weight: .bold)
containerView.layer.mask = textView.layer.sublayers?.last
where GradientView is a UIView subclass similar to :
class GradientView: UIView{
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func addGradient(){
let gradient = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = [UIColor.blue.cgColor,UIColor.red.cgColor,UIColor.green.cgColor]
gradient.startPoint = CGPoint(x: 0, y: 1)
gradient.endPoint = CGPoint(x: 1, y: 0)
gradient.locations = [0,0.5,1]
self.layer.addSublayer(gradient)
}
}
Should look something like this. Maybe your gradient colours would look better.

Related

How to layout 2 StackView of different sizes in a ScrollView

I am trying to fit 2 stackView in one ScrollView
I decided to create a generic StackView that will contain the other two StackViews and place it in a ScrollView
But my left StackView contains 1 item and the second contains 2 items
Code bellow:
let categoryViewsForLeftColumn = categoryViews.split()[0]
let categoryViewsForRightColumn = categoryViews.split()[1]
let leftColumnStackView = UIStackView(arrangedSubviews: categoryViewsForLeftColumn)
leftColumnStackView.translatesAutoresizingMaskIntoConstraints = false
leftColumnStackView.axis = .vertical
leftColumnStackView.spacing = 20
leftColumnStackView.distribution = .fillEqually
let rightColumnStackView = UIStackView(arrangedSubviews: categoryViewsForRightColumn)
rightColumnStackView.translatesAutoresizingMaskIntoConstraints = false
rightColumnStackView.axis = .vertical
rightColumnStackView.spacing = 20
rightColumnStackView.distribution = .fillEqually
let generalStackView = UIStackView(arrangedSubviews: [leftColumnStackView, rightColumnStackView])
generalStackView.translatesAutoresizingMaskIntoConstraints = false
generalStackView.axis = .horizontal
generalStackView.spacing = 20
generalStackView.distribution = .fillEqually
categoriesScrollView.addSubview(generalStackView)
leftColumnStackView.backgroundColor = .green
rightColumnStackView.backgroundColor = .red
NSLayoutConstraint.activate([
generalStackView.widthAnchor.constraint(equalTo: categoriesScrollView.widthAnchor, constant: -10),
generalStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.leadingAnchor, constant: 5),
generalStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.trailingAnchor, constant: -5),
generalStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
generalStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5)
])
result bellow:
I expect items to be the same size
I was trying to post 2 StackView to ScrollView
code bellow:
categoriesScrollView.addSubview(leftColumnStackView)
categoriesScrollView.addSubview(rightColumnStackView)
leftColumnStackView.backgroundColor = .green
rightColumnStackView.backgroundColor = .red
NSLayoutConstraint.activate([
leftColumnStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.leadingAnchor, constant: 5),
leftColumnStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.centerXAnchor, constant: -5),
leftColumnStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
leftColumnStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5),
rightColumnStackView.leadingAnchor.constraint(equalTo: categoriesScrollView.centerXAnchor, constant: 5),
rightColumnStackView.trailingAnchor.constraint(equalTo: categoriesScrollView.trailingAnchor, constant: -5),
rightColumnStackView.topAnchor.constraint(equalTo: categoriesScrollView.topAnchor, constant: 5),
rightColumnStackView.bottomAnchor.constraint(equalTo: categoriesScrollView.bottomAnchor, constant: -5)
])
But it only got worse
result bellow:
The result I want to achieve:
Does anyone know how to achieve this?
If you want to create a "grid" like that without using a collection view (and there are many good reasons not to), you can do it with stack views.
However, instead of think in terms of a horizontal stack view with two vertical "column" stack views, think about a vertical stack view with "rows" of horizontal stack views.
Here's a quick example...
First, a custom view with rounded sides, an image view and a label:
class PillView: UIView {
let imgView = UIImageView()
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
label.numberOfLines = 0
imgView.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
addSubview(imgView)
addSubview(label)
NSLayoutConstraint.activate([
imgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16.0),
imgView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: 12.0),
imgView.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -12.0),
imgView.centerYAnchor.constraint(equalTo: centerYAnchor),
imgView.widthAnchor.constraint(equalToConstant: 36.0),
imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor),
label.topAnchor.constraint(equalTo: topAnchor, constant: 8.0),
label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0),
label.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 8.0),
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16.0),
])
layer.borderColor = UIColor.lightGray.cgColor
layer.borderWidth = 1
}
override var bounds: CGRect {
get { return super.bounds }
set(newBounds) {
super.bounds = newBounds
layer.cornerRadius = newBounds.size.height / 2.0
}
}
}
Now, a sample controller:
class SampleViewController: UIViewController {
let numViews: Int = 5
override func viewDidLoad() {
super.viewDidLoad()
let outerVerticalStack = UIStackView()
outerVerticalStack.axis = .vertical
outerVerticalStack.spacing = 20
outerVerticalStack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(outerVerticalStack)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
outerVerticalStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
outerVerticalStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
outerVerticalStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
])
var j: Int = 0
while j < numViews {
let rowStack = UIStackView()
rowStack.axis = .horizontal
rowStack.spacing = 20
rowStack.distribution = .fillEqually
let v = PillView()
if j == 2 {
v.label.text = "View \(j)\ntwo lines"
} else {
v.label.text = "View \(j)"
}
if let img = UIImage(systemName: "\(j).square.fill") {
v.imgView.image = img
}
rowStack.addArrangedSubview(v)
j += 1
if j < numViews {
let v = PillView()
v.label.text = "View \(j)"
if let img = UIImage(systemName: "\(j).square.fill") {
v.imgView.image = img
}
rowStack.addArrangedSubview(v)
} else {
let v = UIView()
rowStack.addArrangedSubview(v)
}
j += 1
outerVerticalStack.addArrangedSubview(rowStack)
}
}
}
The result looks like this:

The shadow added to the view created is not appearing

I am adding programatically a UIView, and setting its contsraints using NSLayoutConstraint as below, yet teh shadow is not being added.
For the shadow i am using SwifterSwift .addShadow()
UiView:
lazy var alertViewNew: UIView = {
let view = UIView()
view.layer.zPosition = 1
view.cornerRadius = 20
view.addShadow(ofColor: .lightGray, radius: 3, offset: .zero, opacity: 0.3)
view.translatesAutoresizingMaskIntoConstraints = false
return alertView
}()
Adding the Constaraints
func setUpAlertView() {
[alertViewNew].forEach {
(view.addSubview($0))
}
NSLayoutConstraint.activate([
alertViewNew.centerYAnchor.constraint(equalTo: view.centerYAnchor),
alertViewNew.centerXAnchor.constraint(equalTo: view.centerXAnchor),
alertViewNew.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
alertViewNew.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
titleLabel.leadingAnchor.constraint(equalTo: alertViewNew.leadingAnchor, constant: 20),
titleLabel.trailingAnchor.constraint(equalTo: alertViewNew.trailingAnchor, constant: -20),
titleLabel.topAnchor.constraint(equalTo: alertViewNew.topAnchor, constant: 20),
descriptionLabel.leadingAnchor.constraint(equalTo: alertViewNew.leadingAnchor, constant: 20),
descriptionLabel.trailingAnchor.constraint(equalTo: alertViewNew.trailingAnchor, constant: -20),
descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20),
updateButton.topAnchor.constraint(equalTo: descriptionLabel.bottomAnchor, constant: 5),
updateButton.trailingAnchor.constraint(equalTo: alertViewNew.trailingAnchor, constant: -20),
updateButton.widthAnchor.constraint(equalToConstant: 65),
updateButton.bottomAnchor.constraint(equalTo: alertViewNew.bottomAnchor, constant: -20),
])
}
AddShadow by Swifter Swift
func addShadow(ofColor color: UIColor = UIColor(red: 0.07, green: 0.47, blue: 0.57, alpha: 1.0), radius: CGFloat = 3, offset: CGSize = .zero, opacity: Float = 0.5) {
layer.shadowColor = color.cgColor
layer.shadowOffset = offset
layer.shadowRadius = radius
layer.shadowOpacity = opacity
layer.masksToBounds = false
}
Things i tried to fix the issue
Setting mask to bound to true
setting is opaque to true
and some other trials found on stackoverflow
None of this worked
It's a bit difficult to help, because the code you've shown is incomplete (and has errors, as written).
For example, I assume your func addShadow is in a UIView extension like this:
extension UIView {
func addShadow(ofColor color: UIColor = UIColor(red: 0.07, green: 0.47, blue: 0.57, alpha: 1.0), radius: CGFloat = 3, offset: CGSize = .zero, opacity: Float = 0.5) {
layer.shadowColor = color.cgColor
layer.shadowOffset = offset
layer.shadowRadius = radius
layer.shadowOpacity = opacity
// no need for this
//layer.masksToBounds = false
}
}
Next, your lazy var alertViewNew:
lazy var alertViewNew: UIView = {
let view = UIView()
// no logical reason for this
//view.layer.zPosition = 1
// .cornerRadius is not a property of `UIView`
//view.cornerRadius = 20
// assuming this is in a UIView extension
view.addShadow(ofColor: .lightGray, radius: 3, offset: .zero, opacity: 0.3)
view.translatesAutoresizingMaskIntoConstraints = false
// no such thing as alertView
//return alertView
return view
}()
However... if we assume you have code that actually works (labels are defined and created somewhere, subviews are added correctly, etc), the most likely reason you're not seeing the shadow is because your alertViewNew probably has a clear background. If it is clear, there is nothing there to "cast a shadow."
Try setting alertViewNew.backgroundColor = .white and see if that fixes the problem.
Or, try this working example:
class CustomAlertTestVC: UIViewController {
lazy var alertViewNew: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(alertViewNew)
setUpAlertView()
}
func setUpAlertView() {
let titleLabel = UILabel()
let descriptionLabel = UILabel()
let updateButton = UIButton()
titleLabel.font = .boldSystemFont(ofSize: 16.0)
titleLabel.text = "New Version Available"
descriptionLabel.font = .systemFont(ofSize: 16.0)
descriptionLabel.numberOfLines = 0
descriptionLabel.text = "Please, Update application to the new version to continue."
updateButton.setTitle("UPDATE", for: [])
updateButton.setTitleColor(.systemBlue, for: [])
[titleLabel, descriptionLabel, updateButton].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
alertViewNew.addSubview($0)
}
NSLayoutConstraint.activate([
alertViewNew.centerYAnchor.constraint(equalTo: view.centerYAnchor),
// no need for centerX since we're adding leading and trailing constraints
//alertViewNew.centerXAnchor.constraint(equalTo: view.centerXAnchor),
alertViewNew.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
alertViewNew.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
titleLabel.leadingAnchor.constraint(equalTo: alertViewNew.leadingAnchor, constant: 20),
titleLabel.trailingAnchor.constraint(equalTo: alertViewNew.trailingAnchor, constant: -20),
titleLabel.topAnchor.constraint(equalTo: alertViewNew.topAnchor, constant: 20),
descriptionLabel.leadingAnchor.constraint(equalTo: alertViewNew.leadingAnchor, constant: 20),
descriptionLabel.trailingAnchor.constraint(equalTo: alertViewNew.trailingAnchor, constant: -20),
descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20),
updateButton.topAnchor.constraint(equalTo: descriptionLabel.bottomAnchor, constant: 5),
updateButton.trailingAnchor.constraint(equalTo: alertViewNew.trailingAnchor, constant: -20),
// really no need for width constraint
//updateButton.widthAnchor.constraint(equalToConstant: 65),
updateButton.bottomAnchor.constraint(equalTo: alertViewNew.bottomAnchor, constant: -20),
])
alertViewNew.layer.shadowColor = UIColor.lightGray.cgColor
alertViewNew.layer.shadowOffset = .zero
alertViewNew.layer.shadowRadius = 3.0
alertViewNew.layer.shadowOpacity = 0.3
alertViewNew.layer.cornerRadius = 20.0
// to get the view's layer to "cast a shadow"
// either set the view's backgroundColor
alertViewNew.backgroundColor = .white
// or, set the layer's backgroundColor
//alertViewNew.layer.backgroundColor = UIColor.white.cgColor
}
}
Output:

Custom Button Subviews not Showing

I am creating a custom button and the code for this is below. All the styling elements are working, however my the name and image subviews are not being added. I am sure this is a simple error, but I would appreciate it if someone could help me. Thank you.
class MaterialButton: UIButton {
let name = UILabel()
let image = UIImageView()
override init(frame: CGRect) {
super.init(frame: frame)
setupButton()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
setupButton()
}
func setupButton() {
name.textColor = .white
// name.font = UIFont(name: "HelveticaNeue-UltraLight",size: 10.0)
name.textAlignment = .center
self.layer.cornerRadius = 20
addSubview(name)
positionName()
addSubview(image)
positionImage()
}
func positionName() {
name.translatesAutoresizingMaskIntoConstraints = false
name.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 10).isActive = true
name.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
name.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
name.heightAnchor.constraint(equalToConstant: self.bounds.height - image.bounds.height - 20).isActive = true
}
func positionImage() {
image.translatesAutoresizingMaskIntoConstraints = false
image.heightAnchor.constraint(equalToConstant: image.bounds.width).isActive = true
image.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
image.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
image.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
}
}
Example of how button is implemented (other button was declared initialized with Material Button earlier in the code)
func setupOtherButton() { // Setting up plastic button
otherButton.name.text = "Other"
otherButton.name.textColor = .white
otherButton.backgroundColor = .gray
miniSV1.addSubview(otherButton) // Add plastic button to view
otherButton.addTarget(self, action: #selector(otherButtonTapped), for: .touchUpInside)
}
Well don't know the exact UI that you are implementing but I did some changes in your code and got the following UI:
So for the button in viewDidLoad :
class ViewController: UIViewController {
var otherButton = MaterialButton()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
otherButton.frame = CGRect(x: 10, y: 180, width: 140, height: 140)
otherButton.name.text = "Other"
otherButton.name.textColor = .white
otherButton.backgroundColor = .gray
self.view.addSubview(otherButton)
}
}
And few changes in the constraints:
class MaterialButton: UIButton {
let name = UILabel()
let image = UIImageView()
override init(frame: CGRect) {
super.init(frame: frame)
setupButton()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
setupButton()
}
func setupButton() {
image.backgroundColor = UIColor.yellow
addSubview(image)
positionImage()
name.textColor = .white
name.textAlignment = .center
name.backgroundColor = .blue
self.layer.cornerRadius = 20
addSubview(name)
positionName()
}
func positionName() {
name.translatesAutoresizingMaskIntoConstraints = false
name.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true
name.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
name.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
name.heightAnchor.constraint(equalToConstant: 20).isActive = true
}
func positionImage() {
image.translatesAutoresizingMaskIntoConstraints = false
image.heightAnchor.constraint(equalToConstant: 50).isActive = true
image.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
image.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
image.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
}
}
Check out this URL for better understanding of the constraints programmatically:
How to add constraints programmatically using Swift

UIImage Aspect Fill and clipsToBounds

I want to set an image to a UIImage, but as soon as I set it it the UIImageView gets bigger and goes over other elements.
There is a solution provided here:
Crop UIImage to fit a frame image
But I can not get it to work, I set the properties like in the solution provided.
Maybe somebody can have a look and help me:
Without setting the image:
After setting the image:
class Cell: UICollectionViewCell, CollectionViewCellConfigurable {
var image = UIImageView()
var dateDay = UILabel()
var dateMonth = UILabel()
var title = UILabel()
lazy private var dateContainer: UIView = {
let v = UIView()
v.sv(dateDay, dateMonth)
dateDay.heightAnchor.constraint(equalTo: self.dateMonth.heightAnchor, multiplier: 1).isActive = true
dateDay.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 5).isActive = true
dateDay.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -5).isActive = true
dateDay.topAnchor.constraint(equalTo: v.topAnchor, constant: 15).isActive = true
dateDay.bottomAnchor.constraint(equalTo: dateMonth.topAnchor, constant: -5).isActive = true
dateMonth.heightAnchor.constraint(equalTo: self.dateDay.heightAnchor, multiplier: 1).isActive = true
dateMonth.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 5).isActive = true
dateMonth.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -5).isActive = true
dateMonth.topAnchor.constraint(equalTo: dateDay.bottomAnchor, constant: 5).isActive = true
// dateMonth.bottomAnchor.constraint(greaterThanOrEqualTo: v.bottomAnchor, constant: -5).isActive = true
return v
}()
lazy private var container: UIView = {
return UIView()
}()
func configureCellAtIndexPath(item: Journaling) {
self.image.image = UIImage.baliBeach
self.image.backgroundColor = .green
self.dateDay.text = "16"
self.dateMonth.text = "May"
self.title.text = "Text visible"
}
override init(frame: CGRect) {
super.init(frame:frame)
setUpLayout()
additionalSetUp()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func additionalSetUp() {
backgroundColor = .clear
let colorText: UIColor = .grau
dateDay.textColor = colorText
dateMonth.textColor = colorText
title.textColor = colorText
dateDay.textAlignment = .center
dateMonth.textAlignment = .center
title.textAlignment = .center
image.contentMode = .scaleAspectFill
image.clipsToBounds = true
image.autoresizesSubviews = true
}
func setUpLayout() {
sv(dateContainer, container)
container.sv(image,title)
dateContainer.widthAnchor.constraint(equalToConstant: 45).isActive = true
// dateContainer.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.15).isActive = true
dateContainer.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
dateContainer.trailingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
dateContainer.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
dateContainer.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
// container.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.5).isActive = true
container.leadingAnchor.constraint(equalTo: dateContainer.trailingAnchor, constant: 0).isActive = true
container.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
container.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
container.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
image.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 5).isActive = true
image.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -5).isActive = true
image.topAnchor.constraint(equalTo: self.topAnchor, constant: 15).isActive = true
image.bottomAnchor.constraint(equalTo: title.topAnchor, constant: -5).isActive = true
title.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
title.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: 0).isActive = true
title.topAnchor.constraint(equalTo: image.bottomAnchor, constant: 5).isActive = true
title.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: 0).isActive = true
}
}
You need to higher vertical compression priority of the title label as the imageView is equal it = 750 , so it occupies the space
title.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 751), for: .vertical)

Swift - Adding left border to UITableViewCell

I'm trying to set left border to each table view cell programmatically. I'm using UIView as a border but I cannot display the UIView for some reason. Also how should I set the UIView height? Thank you.
class Cell: UITableViewCell {
var borderLeft: UIView = {
let view = UIView()
view.frame.size.width = 3
view.frame.size.height = 20
view.backgroundColor = .red
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.backgroundColor = .black
addSubview(borderLeft)
borderLeft.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
borderLeft.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
borderLeft.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I think there is a mistake on this anchor:
borderLeft.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
try instead to swap with bottomAnchor, like:
borderLeft.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
also add constraints for width and height (please remove frame resizing since is being ignored by view.translatesAutoresizingMaskIntoConstraints = false)
borderLeft.heightAnchor.constraint(equalToConstant: 20).isActive = true
borderLeft.widthAnchor.constraint(equalToConstant: 3).isActive = true
borderLeft.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
borderLeft.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
here the result: