Is it possible to add constraint between two UILabels? - swift

Yeah basically i want to create a constraint between the bottom border of one UILabel (label1) and top border of another UILabel (label2). I currently have the top of my label 1 connected to the safearea and constant height set up to 100.
let label1 = UILabel.init()
label1.text = "123"
view.addSubview(label1)
label1.translatesAutoresizingMaskIntoConstraints = false
label1.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
label1.heightAnchor.constraint(equalToConstant: 100).isActive = true
let label2 = UILabel.init()
label2.text = "456"
view.addSubview(label2)
label2.translatesAutoresizingMaskIntoConstraints = false
label2.topAnchor.constraint(???)

You need
let label1 = UILabel()
label1.text = "123"
view.addSubview(label1)
label1.translatesAutoresizingMaskIntoConstraints = false
let label2 = UILabel()
label2.text = "456"
view.addSubview(label2)
label2.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label1.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor,constant:20.0),
label1.centerXAnchor.constraint(equalTo:self.view.centerXAnchor),
label2.topAnchor.constraint(equalTo: self.label1.bottomAnchor,constant:20.0),
label2.centerXAnchor.constraint(equalTo:self.view.centerXAnchor)
])
You can also use a vertical UIStackView

Simply use vertical stackview .
let label1 = UILabel()
label1.text = "123"
let label2 = UILabel()
label2.text = "456"
let stackView = UIStackView(arrangedSubviews: [label1, label2])
stackView.axis = .vertical
stackView.distribution = .equalSpacing
stackView.alignment = .center
stackView.spacing = 10
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor,constant:20.0),
stackView.centerXAnchor.constraint(equalTo:self.view.centerXAnchor)
])

Related

How to make vertical labels bar in Swift?

I would like to make such layout via swift:
I tried to make it in such way:
var buttonArray = [UILabel]()
for (myKey,myValue) in colorDictionary{
buttonArray += [colorButton(withColor: myValue, title: myKey)]
}
let horizontalStack = UIStackView(arrangedSubviews: buttonArray)
horizontalStack.axis = .horizontal
horizontalStack.distribution = .fillEqually
horizontalStack.alignment = .fill
horizontalStack.translatesAutoresizingMaskIntoConstraints = false
horizontalStack.transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
let label2 = UILabel()
label2.text = "Label"
label2.backgroundColor = .red
label2.textColor = .white
label2.textAlignment = .center
label2.lineBreakMode = .byCharWrapping
label2.numberOfLines = 0
label2.translatesAutoresizingMaskIntoConstraints = false
label2.transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
let mainStackView = UIStackView()
mainStackView.axis = .horizontal
mainStackView.translatesAutoresizingMaskIntoConstraints = false
mainStackView.addArrangedSubview(label2)
mainStackView.addArrangedSubview(horizontalStack)
mainContainer.addSubview(mainStackView)
NSLayoutConstraint.activate([
mainStackView.topAnchor.constraint(equalTo: mainContainer.topAnchor, constant: 5),
mainStackView.leftAnchor.constraint(equalTo: mainContainer.leftAnchor,
constant: 20),
mainStackView.rightAnchor.constraint(equalTo: mainContainer.rightAnchor,
constant: -20),
mainStackView.heightAnchor.constraint(equalToConstant: 270),
])
where colorButton is:
func colorButton(withColor color:UIColor, title:String) -> UILabel{
let newButton = UILabel()
newButton.backgroundColor = color
newButton.text = title
newButton.textAlignment = .center
newButton.textColor = UIColor.white
return newButton
}
and here is the result which I got:
How I can make all these labels look like the desired image? And also I'm not sure whether label rotation can be done by my method.
What I would do is first get it working without any transformations so it appears as a normal, not rotated setup. Once that is working, you only need to apply a single transformation to the main stack view to get the whole thing rotated. Then finally you can tweak the constraints to get it positioned correctly.
Here is code that works:
let horizontalStack = UIStackView(arrangedSubviews: buttonArray)
horizontalStack.axis = .horizontal
horizontalStack.distribution = .fillEqually
horizontalStack.alignment = .fill
horizontalStack.translatesAutoresizingMaskIntoConstraints = false
let label2 = UILabel()
label2.text = "Label"
label2.backgroundColor = .red
label2.textColor = .white
label2.textAlignment = .center
label2.lineBreakMode = .byCharWrapping
label2.numberOfLines = 0
label2.translatesAutoresizingMaskIntoConstraints = false
let mainStackView = UIStackView()
mainStackView.axis = .vertical
mainStackView.distribution = .equalSpacing
mainStackView.translatesAutoresizingMaskIntoConstraints = false
mainStackView.addArrangedSubview(label2)
mainStackView.addArrangedSubview(horizontalStack)
mainStackView.transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
mainContainer.addSubview(mainStackView)
NSLayoutConstraint.activate([
mainStackView.centerYAnchor.constraint(equalTo: mainContainer.centerYAnchor),
mainStackView.centerXAnchor.constraint(equalTo: mainContainer.leftAnchor, constant: 40),
// Set the "width", not the "height"
mainStackView.widthAnchor.constraint(equalToConstant: 270),
])
Changes:
I removed the transformation you had for the horizontal stack view and the big label.
I added a single transformation to the main stack view.
I used a vertical, not horizontal, stack view for the main stack.
Updated the properties of the main stack view so the main label fills the area above the other labels.
Updated the constraints. Adjust those to suit your needs.
Note that you need to set the width of the main stack view since the constraint is relative to the untransformed main stack view.

StackView with two labels doesn't wrap content

I have one StackView with two labels inside. I want to place the two labels one next to the other.
private lazy var stackView: UIStackView = {
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.alignment = .center
stackView.axis = .horizontal
stackView.backgroundColor = .black
stackView.spacing = 10
return stackView
}()
// MARK: Labels
private lazy var firstLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.textColor = UIColor.brandColor(.white)
label.textAlignment = .right
label.font = UIFont.bloomSpeakFont(.titleUltraHeavy, ofSize: 8.0)
return label
}()
private lazy var secondLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.textColor = UIColor.brandColor(.white)
label.textAlignment = .right
label.font = UIFont.bloomSpeakFont(.bodyExtraBold, ofSize: 10.0)
return label
}()
// MARK: - Setup
private func setupStackView() {
stackView.addArrangedSubview(firstLabel)
//firstLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
//firstLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true
//firstLabel.setContentHuggingPriority(UILayoutPriority.defaultLow, for: .horizontal)
stackView.addArrangedSubview(secondLabel)
//secondLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
//secondLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true
//secondLabel.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .horizontal)
addSubview(stackView)
stackView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
}
My problem is:
What I want:
The label next to the number and also some padding some padding with the margins.
Thanks in advance.
EDIT
After set spacing to 0, numberOfLines to 1, stackView.alignment = .fill I got the result bellow. I just wonder how to add padding to the labels?
Thanks to the comments of #SandeepBhandari and #DonMag i could solved my issue:
The final solution was:
private lazy var stackView: UIStackView = {
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.alignment = .fill // << changed from .center to .fill
stackView.axis = .horizontal
stackView.backgroundColor = .black
//stackView.spacing = 10 << removed line
return stackView
}()
// MARK: Labels
private lazy var firstLabel: PaddingLabel = {
let label = PaddingLabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 1 // << changed from 0 to 1
label.textColor = UIColor.brandColor(.white)
label.textAlignment = .right
label.font = UIFont.bloomSpeakFont(.titleUltraHeavy, ofSize: 8.0)
return label
}()
private lazy var secondLabel: PaddingLabel = {
let label = PaddingLabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 1
label.textColor = UIColor.brandColor(.white)
label.textAlignment = .right
label.font = UIFont.bloomSpeakFont(.bodyExtraBold, ofSize: 10.0)
return label
}()
// MARK: - Setup
private func setupStackView() {
stackView.addArrangedSubview(firstLabel)
stackView.addArrangedSubview(secondLabel)
firstLabel.paddingLeft = 2
firstLabel.paddingRight = 1
secondLabel.paddingLeft = 1
secondLabel.paddingRight = 2
addSubview(stackView)
stackView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
}
I also use this guide https://johncodeos.com/how-to-add-padding-in-uilabel-in-ios-using-swift/, to add padding to the labels.
The final result is:

Cannot change label position in stackview swift

I want to change X position of a label inside a stackview, there is a button inside the stackview as well. However, I am not able to change the label's position as once I set constraints for the label, errors jump out and want me to delete the constraints.
This is an example of a stackview with a button and a label with changes to the label's x position.
import UIKit
class ViewController: UIViewController {
let stackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
stackView.axis = .vertical
stackView.distribution = .equalSpacing
stackView.alignment = .center
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
stackView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
stackView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
let button = UIButton()
button.setTitle("Button", for: .normal)
button.setTitleColor(UIColor.black, for: .normal)
button.backgroundColor = UIColor.lightGray
stackView.addArrangedSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.leftAnchor.constraint(equalTo: stackView.leftAnchor).isActive = true
button.rightAnchor.constraint(equalTo: stackView.rightAnchor).isActive = true
let label = UILabel()
label.text = "Label"
label.textColor = UIColor.black
label.backgroundColor = UIColor.lightGray
stackView.addArrangedSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
// Modify left/right anchor constraints for label x position
label.leftAnchor.constraint(equalTo: stackView.leftAnchor, constant: 24).isActive = true
label.rightAnchor.constraint(equalTo: stackView.rightAnchor).isActive = true
}
}

Horizontal Stackview left align items

I am creating a horizontal UIStackView and want to left align items in it.
Here is my code:
let nameLabel: UILabel = {
let label=UILabel()
label.text = "First Name:"
label.textColor = UIColor.black
label.font = UIFont.systemFont(ofSize: 20)
label.textAlignment = .left
label.translatesAutoresizingMaskIntoConstraints=false
return label
}()
let nameTextField: UITextField = {
let label=UITextField()
label.placeholder = "Enter Name"
label.textColor = UIColor.darkGray
label.font = UIFont.systemFont(ofSize: 18)
label.textAlignment = .left
label.isUserInteractionEnabled = false
label.translatesAutoresizingMaskIntoConstraints=false
return label
}()
lazy var firstNameView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.nameLabel, self.nameTextField])
stackView.translatesAutoresizingMaskIntoConstraints = false;
stackView.axis = .horizontal
stackView.distribution = .fill
stackView.alignment = .center
stackView.spacing = 10.0
return stackView
}()
And here is how i add it to the view
self.view.addSubview(firstNameView)
firstNameView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true;
firstNameView.topAnchor.constraint(equalTo: idLabel.bottomAnchor).isActive = true;
firstNameView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
firstNameView.heightAnchor.constraint(equalToConstant: 40.0).isActive = true
I also tried the following:
firstNameView.trailingAnchor.constraint(greaterThanOrEqualTo: self.view.trailingAnchor).isActive = true
PS: This question is different from UIStackview align left as i am talking about horizontal stackview
According to this link Left aligned horizontal stackview and top aligned vertical stackview
Is there any alternative, i don't really want to set a fixed width.
Wrap your labels in UIViews and pin the labels to the left of these views. Put the views into the stack view and they will fill the stack view without manipulating the labels.

label showing top of screen instead of being on the inputAccessoryView

Here is my code:
var messageView : UITextView = {
var textView = UITextView()
textView.text = " Add your message here"
textView.textColor = UIColor.lightGrayColor()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.backgroundColor = UIColor.lightGrayColor()
textView.layer.cornerRadius = 3
textView.clipsToBounds = true
textView.keyboardAppearance = .Dark
textView.layer.borderWidth = 1.0
textView.layer.borderColor = UIColor.lightGrayColor()
textView.autocorrectionType = .no
// MARK: Setup accesorryView
let label = UILabel()
label.text = "You have a 100 character limit"
label.translatesAutoresizingMaskIntoConstraints = false
let accessoryView = UIView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, 44))
accessoryView.backgroundColor = UIColor.redColor()
accessoryView.addSubview(label)
accessoryView.leadingAnchor.constraintEqualToAnchor(label.leadingAnchor, constant: 18)
accessoryView.centerYAnchor.constraintEqualToAnchor(label.centerYAnchor)
textView.inputAccessoryView = accessoryView
return textView
}()
I'm trying to add an inputAccessoryView to my TextView's keyboard.
My inputAccessoryView must have a label saying "You have a 100 character limit"...
But my current result is as:
The text in the blue...is exactly the label I want to be in the inputAccessoryView, but it's on the top of my screen...
You need to set translatesAutoresizingMaskIntoConstraints on the label to false and isActive to true on the constraints. Basically your constrains code should look like this:
accessoryView.leadingAnchor.constraintEqualToAnchor(label.leadingAnchor, constant: 18).isActive = true
accessoryView.centerYAnchor.constraintEqualToAnchor(label.centerYAnchor).isActive = true
As per my understanding, try this:
Swift 3
let accessoryView = UIView()
let label = UILabel()
let counterLabel = UILabel()//This is the counter label
label.text = "You have a 100 character limit"
counterLabel.text = "100"
accessoryView.frame = CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 44)
accessoryView.backgroundColor = UIColor.red
accessoryView.addSubview(label)
accessoryView.addSubview(counterLabel)
// to setup contraint set below property to false.
label.translatesAutoresizingMaskIntoConstraints = false
counterLabel.translatesAutoresizingMaskIntoConstraints = false
//label constrint with 0 padding from left side. To change padding from left and right side, change the constant value.
accessoryView.leadingAnchor.constraint(equalTo: label.leadingAnchor, constant: 0).isActive = true
accessoryView.centerYAnchor.constraint(equalTo: label.centerYAnchor).isActive = true
//counterl=Label constrint with 0 padding from right side
accessoryView.trailingAnchor.constraint(equalTo:counterLabel.trailingAnchor, constant: 0).isActive = true
accessoryView.centerYAnchor.constraint(equalTo: counterLabel.centerYAnchor).isActive = true
textView.inputAccessoryView = accessoryView