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
}
}
Related
I can easily create a stackview with rounded corners in iOS 14 by doing:
stackView.layer.cornerRadius = 10
stackView.clipsToBounds = true
without doing anything else. But since I want my app to also work on iPhone 6 that can't go beyond iOS 12, the above 2 lines of code don't do anything. I have looked at How can I set the cornerRadius of a UIStackView? and adapted the code to my app, but it still doesn't work. To be clear, I have:
Changed my build settings to use a deployment target of iOS 12.3
Excluded references to scenes and added window variable (Add iOS 12 support to a new Xcode 11 Project)
Tested with iPhone 11 and iphone 6 simulator (both did not show rounded corners)
Here's my code:
import UIKit
class ViewController: UIViewController {
let buttonList = ["Dog", "Cat", "Mouse"]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
let stackView = UIStackView()
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.alignment = .fill
stackView.spacing = 6
stackView.backgroundColor = .systemPink // this actually works
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
stackView.widthAnchor.constraint(equalToConstant: 140).isActive = true
// The following is "supposed" to create rounded corners for the stackview
let subView = UIView(frame: stackView.bounds)
subView.backgroundColor = .yellow // this ends up showing through instead of the systemPink
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
stackView.insertSubview(subView, at: 0)
subView.layer.cornerRadius = 10
subView.layer.masksToBounds = true
subView.clipsToBounds = true
// Fill the stackview with buttons
for index in 0..<buttonList.count {
let button = UIButton()
button.setTitle(buttonList[index], for: .normal)
button.backgroundColor = .cyan
button.setTitleColor(.black, for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 14)
stackView.addArrangedSubview(button)
}
}
}
And this is what it looks like (no rounded corners):
So what am I missing? How can I make my stackview appear to have rounded corners for iPhone 6 (iOS 12) and above?
You could place your stackView inside another view and set background color/corner radius for this container view:
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
// The following is "supposed" to create rounded corners for the stackview
let subView = UIView()
subView.backgroundColor = .yellow // this ends up showing through instead of the systemPink
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
subView.layer.cornerRadius = 10
subView.layer.masksToBounds = true
subView.clipsToBounds = true
view.addSubview(subView)
subView.translatesAutoresizingMaskIntoConstraints = false
let stackView = UIStackView()
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.alignment = .fill
stackView.spacing = 6
stackView.backgroundColor = .systemPink // this actually works
subView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
// Fill the stackview with buttons
for index in 0..<buttonList.count {
let button = UIButton()
button.setTitle(buttonList[index], for: .normal)
button.backgroundColor = .cyan
button.setTitleColor(.black, for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 14)
stackView.addArrangedSubview(button)
}
NSLayoutConstraint.activate([
stackView.trailingAnchor.constraint(equalTo: subView.trailingAnchor),
stackView.leadingAnchor.constraint(equalTo: subView.leadingAnchor),
stackView.topAnchor.constraint(equalTo: subView.topAnchor),
stackView.bottomAnchor.constraint(equalTo: subView.bottomAnchor),
subView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
subView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
subView.widthAnchor.constraint(equalToConstant: 140)
])
}
As far as I know, it is also better to activate NSLayoutConstraint in a group, not one by one
what is wrong with my StackView?
This is the code:
class PushUpViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setUpStackView()
}
func setUpStackView() {
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .fillProportionally
stackView.spacing = 50
view.addSubview(stackView)
// SetUp StackView Constraints:
stackView.pin(to: view)
stackView.setCustomSpacing(50, after: PushUpButton)
stackView.setCustomSpacing(100, after: TimeLabel)
// Set Elements to StackView:
stackView.addArrangedSubview(TimeLabel)
stackView.addArrangedSubview(PushUpButton)
stackView.addArrangedSubview(secondStackView)
// SetUp PushUpButton:
PushUpButton.backgroundColor = .white
PushUpButton.setTitle("\(count)", for: .normal)
PushUpButton.setTitleColor(.systemGray, for: .normal)
PushUpButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 70)
PushUpButton.translatesAutoresizingMaskIntoConstraints = false
PushUpButton.heightAnchor.constraint(equalToConstant: 300).isActive = true
PushUpButton.widthAnchor.constraint(equalToConstant: 150).isActive = true
// SetUp TimeLabel
TimeLabel.textAlignment = .center
TimeLabel.text = "\(counter)"
TimeLabel.textColor = .black
TimeLabel.font = .boldSystemFont(ofSize: 30)
self.view.addSubview(TimeLabel)
TimeLabel.translatesAutoresizingMaskIntoConstraints = false
TimeLabel.widthAnchor.constraint(equalToConstant: 300).isActive = true
TimeLabel.heightAnchor.constraint(equalToConstant: 200).isActive = true
// SetUp SecondStackView
secondStackView.translatesAutoresizingMaskIntoConstraints = false
secondStackView.axis = .horizontal
secondStackView.alignment = .center
secondStackView.distribution = .fillEqually
secondStackView.spacing = 20
// SetUp SecondStackView Constrains
secondStackView.heightAnchor.constraint(equalToConstant: 50).isActive = true
secondStackView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -15).isActive = true
// Set Elements:
secondStackView.addArrangedSubview(breakButton)
secondStackView.addArrangedSubview(stopbutton)
//SetUp BreakButton
breakButton.backgroundColor = .lightGray
breakButton.setTitle("Break", for: .normal)
breakButton.setTitle("Start", for: .selected)
breakButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
breakButton.setTitleColor(.white, for: .normal)
breakButton.layer.cornerRadius = 12
breakButton.layer.borderWidth = 1
breakButton.layer.borderColor = UIColor.white.cgColor
// breakButton.addTarget(self, action: #selector(BreakButtonTapped), for: .touchUpInside)
breakButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
breakButton.widthAnchor.constraint(equalToConstant: 150),
breakButton.heightAnchor.constraint(equalToConstant: 50)
])
// SetUp StopButton:
stopbutton.backgroundColor = .systemRed
stopbutton.setTitle("Stop", for: .normal)
stopbutton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
stopbutton.setTitleColor(.white, for: .normal)
stopbutton.layer.cornerRadius = 12
stopbutton.layer.borderWidth = 1
stopbutton.layer.borderColor = UIColor.white.cgColor
// stopbutton.addTarget(self, action: #selector(stopButtonTapped), for: .touchUpInside)
stopbutton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stopbutton.widthAnchor.constraint(equalToConstant: 150),
stopbutton.heightAnchor.constraint(equalToConstant: 50)
])
}
}
And this is how it look:
But it should looks like this:
This is what comes in the console when I am on the StackView VC:
I have no idea what this means or what I should do to solve this problem
I do not understand StackViews... I watched a lot of yt tutorials but they are all the same and did't help me. My biggest problem is the distribution of the StackView: I don't know where the difference is
First tip: forget using .fillProportionally with stack views. It is almost never used ... and when it is used, it's used for very specific reasons.
Second tip: during development, give your UI elements contrasting background colors to make it easy to see the frames at run-time.
Third tip: Use leadingLowerCase for variable and function names... Use LeadingUpperCase for class names.
Fourth tip: group similar code together - such as setting view properties, setting constraints, etc - and include logical comments to make it easier to follow what your code is doing.
Take a look at this:
class PushUpViewController: UIViewController {
let stackView = UIStackView()
let secondStackView = UIStackView()
let pushUpButton = UIButton()
let breakButton = UIButton()
let stopbutton = UIButton()
let timeLabel = UILabel()
var count: Int = 0
var counter: Float = 0.0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setUpStackView()
}
func setUpStackView() {
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .fill
stackView.distribution = .fill
// SetUp timeLabel
timeLabel.textAlignment = .center
timeLabel.text = "\(counter)"
timeLabel.textColor = .black
timeLabel.font = .boldSystemFont(ofSize: 30)
// SetUp pushUpButton:
pushUpButton.backgroundColor = .white
pushUpButton.setTitle("\(count)", for: .normal)
pushUpButton.setTitleColor(.systemGray, for: .normal)
pushUpButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 70)
// SetUp secondStackView
secondStackView.axis = .horizontal
secondStackView.alignment = .fill
secondStackView.distribution = .fillEqually
secondStackView.spacing = 20
//SetUp breakButton
breakButton.backgroundColor = .lightGray
breakButton.setTitle("Break", for: .normal)
breakButton.setTitle("Start", for: .selected)
breakButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
breakButton.setTitleColor(.white, for: .normal)
breakButton.layer.cornerRadius = 12
breakButton.layer.borderWidth = 1
breakButton.layer.borderColor = UIColor.white.cgColor
// SetUp stopButton:
stopbutton.backgroundColor = .systemRed
stopbutton.setTitle("Stop", for: .normal)
stopbutton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
stopbutton.setTitleColor(.white, for: .normal)
stopbutton.layer.cornerRadius = 12
stopbutton.layer.borderWidth = 1
stopbutton.layer.borderColor = UIColor.white.cgColor
// add buttons to horizontal second stack view
secondStackView.addArrangedSubview(breakButton)
secondStackView.addArrangedSubview(stopbutton)
// if we want the center PushUpButton to be 300 x 150
// and centered vertically
// we need to embed it in a clear view
let holderView = UIView()
// add PushUpButton to holderView
holderView.addSubview(pushUpButton)
// views added as arrangedSubviews of a stack view automatically get
// .translatesAutoresizingMaskIntoConstraints = false
// but, because we're adding the PushUpButton as a subview
// of holderView, we need to set it here
pushUpButton.translatesAutoresizingMaskIntoConstraints = false
// add views to stack view
stackView.addArrangedSubview(timeLabel)
stackView.addArrangedSubview(holderView)
stackView.addArrangedSubview(secondStackView)
// add stackView to view
view.addSubview(stackView)
// SetUp StackView Constraints:
//stackView.pin(to: view)
// respect safe-area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain stackview to full view (safe-area)
// to bottom with Zero extra space
stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
// to top with 20-pts "padding"
stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
// and 8-pts "padding" on each side
stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
// pushUpButton should be 300x150
pushUpButton.widthAnchor.constraint(equalToConstant: 300.0),
pushUpButton.heightAnchor.constraint(equalToConstant: 150.0),
// pushUpButton should be centered in holderView
pushUpButton.centerXAnchor.constraint(equalTo: holderView.centerXAnchor),
pushUpButton.centerYAnchor.constraint(equalTo: holderView.centerYAnchor),
// bottom buttons should have Height: 50
secondStackView.heightAnchor.constraint(equalToConstant: 50.0),
])
// break and stop button actions
//breakButton.addTarget(self, action: #selector(BreakButtonTapped), for: .touchUpInside)
//stopbutton.addTarget(self, action: #selector(stopButtonTapped), for: .touchUpInside)
// during development, so we can see the layout easily
//holderView.backgroundColor = .yellow
//PushUpButton.backgroundColor = .green
//TimeLabel.backgroundColor = .cyan
}
}
Result on iPhone 11:
on iPhone 8:
and with background colors to help during development:
Additional Tip:
When learning auto layout (particularly stack views), work on your layout in Storyboard / Interface Builder. You can immediately see how it looks and what happens when changing values / properties. You can also change the View as: to immediately see how it looks on different devices / screen sizes. If you want to keep everything in code, once you have your layout looking the way you want, then replicate those constraints and settings in code.
Hey my StackView is doing nothing, there are two problems:
The first is that the elements on the VC are completely displaced when I turn around the simulator or change the device, so the StackView is not doing what it should do!
The second thing is that the StackView is covering the navigation bar and I don't know how to make it visible.
Can someone help me?
import UIKit
class RegisterViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let stackView = UIStackView()
var profilePicture = UIButton()
var profileIcon = UIImage()
let usernameTextField = UITextField()
let emailTextField = UITextField()
let passswordTextField = UITextField()
let signInButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Create an Account"
view.backgroundColor = .white
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .fillEqually
stackView.spacing = 50
view.addSubview(stackView)
// SetUp Stack View Constraints:
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
//Add Elements
stackView.addArrangedSubview(profilePicture)
stackView.addArrangedSubview(usernameTextField)
stackView.addArrangedSubview(passswordTextField)
stackView.addArrangedSubview(signInButton)
// MARK: - Set-Up View-Elements
// SetUp ProfileIcon:
profileIcon = UIImage(named: "characteer")!
profilePicture.setImage(profileIcon, for: .normal)
profilePicture.imageView?.contentMode = .scaleAspectFill
let cornerRadius: CGFloat
cornerRadius = 75 // half of widht/height
profilePicture.layer.cornerRadius = cornerRadius
profilePicture.layer.masksToBounds = true
profilePicture.layer.borderWidth = 1
profilePicture.layer.borderColor = UIColor.white.cgColor
profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
view.addSubview(profilePicture)
profilePicture.translatesAutoresizingMaskIntoConstraints = false
profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
profilePicture.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
profilePicture.topAnchor.constraint(equalTo: view.topAnchor, constant: 110).isActive = true
// SetUp UsernameTextfield:
usernameTextField.backgroundColor = .white
usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
usernameTextField.textAlignment = NSTextAlignment.center
usernameTextField.layer.cornerRadius = 8
usernameTextField.layer.borderWidth = 1
usernameTextField.layer.borderColor = UIColor.lightGray.cgColor
self.view.addSubview(usernameTextField)
let username = usernameTextField.text
usernameTextField.translatesAutoresizingMaskIntoConstraints = false
usernameTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
usernameTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
usernameTextField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
// SetUpEmailTextfield:
emailTextField.backgroundColor = .white
emailTextField.attributedPlaceholder = NSAttributedString(string: "Email", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
emailTextField.textAlignment = NSTextAlignment.center
emailTextField.layer.cornerRadius = 8
emailTextField.layer.borderWidth = 1
emailTextField.layer.borderColor = UIColor.lightGray.cgColor
self.view.addSubview(emailTextField)
emailTextField.translatesAutoresizingMaskIntoConstraints = false
emailTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
emailTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
emailTextField.topAnchor.constraint(equalTo: usernameTextField.bottomAnchor, constant: 20).isActive = true
```
Just I set for profilePicture and usernameTextField but for others are same it works. Wrong side of your code is about constraint and you add object two different views. There is a solution.
let stackView = UIStackView()
var profilePicture = UIButton()
var profileIcon = UIImage()
let usernameTextField = UITextField()
let emailTextField = UITextField()
let passswordTextField = UITextField()
let signInButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Create an Account"
view.backgroundColor = .white
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .fillEqually
stackView.spacing = 50
view.addSubview(stackView)
// SetUp Stack View Constraints:
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
//Add Elements
stackView.addArrangedSubview(profilePicture)
stackView.addArrangedSubview(usernameTextField)
// MARK: - Set-Up View-Elements
// SetUp ProfileIcon:
profileIcon = UIImage(named: "characteer")!
profilePicture.setImage(profileIcon, for: .normal)
profilePicture.imageView?.contentMode = .scaleAspectFill
let cornerRadius: CGFloat
cornerRadius = 75 // half of widht/height
profilePicture.layer.cornerRadius = cornerRadius
profilePicture.layer.masksToBounds = true
profilePicture.layer.borderWidth = 1
profilePicture.layer.borderColor = UIColor.white.cgColor
//profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
profilePicture.translatesAutoresizingMaskIntoConstraints = false
profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
// SetUp UsernameTextfield:
usernameTextField.backgroundColor = .white
usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
usernameTextField.textAlignment = NSTextAlignment.center
usernameTextField.layer.cornerRadius = 8
usernameTextField.layer.borderWidth = 1
usernameTextField.layer.borderColor = UIColor.lightGray.cgColor
let username = usernameTextField.text
usernameTextField.translatesAutoresizingMaskIntoConstraints = false
usernameTextField.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width-40).isActive = true
usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
You're doing a number of things wrong... It would be well worth your while to go through a few tutorials on auto-layout and using UIStackView.
First, if you add a view (image view, text field, label, button, etc) to a stack view, do not also give those views position constraints. That's what the stack view is doing.
Second, once you've added a view:
stackView.addArrangedSubview(profilePicture)
do not then add it as a subview like this:
view.addSubview(profilePicture)
Doing that will remove profilePicture from the stack view.
Take a look through your code -- review the comments where I've made changes:
class RegisterViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let stackView = UIStackView()
var profilePicture = UIButton()
var profileIcon = UIImage()
let usernameTextField = UITextField()
let emailTextField = UITextField()
let passswordTextField = UITextField()
let signInButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Create an Account"
view.backgroundColor = .white
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
// distribution should be .fill NOT .fillEqually
stackView.distribution = .fill
stackView.spacing = 50
view.addSubview(stackView)
// SetUp Stack View Constraints:
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
//Add Elements
stackView.addArrangedSubview(profilePicture)
stackView.addArrangedSubview(usernameTextField)
stackView.addArrangedSubview(emailTextField)
stackView.addArrangedSubview(passswordTextField)
stackView.addArrangedSubview(signInButton)
// MARK: - Set-Up View-Elements
// SetUp ProfileIcon:
//profileIcon = UIImage(named: "characteer")!
profileIcon = UIImage(named: "pro1")!
profilePicture.setImage(profileIcon, for: .normal)
profilePicture.imageView?.contentMode = .scaleAspectFill
let cornerRadius: CGFloat
cornerRadius = 75 // half of widht/height
profilePicture.layer.cornerRadius = cornerRadius
profilePicture.layer.masksToBounds = true
profilePicture.layer.borderWidth = 1
profilePicture.layer.borderColor = UIColor.white.cgColor
//profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
// NO - it's already in the stack view
//view.addSubview(profilePicture)
// Set Only Width and Height - position is managed by the stack view
profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
// SetUp UsernameTextfield:
usernameTextField.backgroundColor = .white
usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
usernameTextField.textAlignment = NSTextAlignment.center
usernameTextField.layer.cornerRadius = 8
usernameTextField.layer.borderWidth = 1
usernameTextField.layer.borderColor = UIColor.lightGray.cgColor
// NO - it's already in the stack view
// self.view.addSubview(usernameTextField)
let username = usernameTextField.text
// Set Only Width and Height - position is managed by the stack view
usernameTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
// SetUpEmailTextfield:
emailTextField.backgroundColor = .white
emailTextField.attributedPlaceholder = NSAttributedString(string: "Email", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
emailTextField.textAlignment = NSTextAlignment.center
emailTextField.layer.cornerRadius = 8
emailTextField.layer.borderWidth = 1
emailTextField.layer.borderColor = UIColor.lightGray.cgColor
// NO - it's already in the stack view
// self.view.addSubview(emailTextField)
// Set Only Width and Height - position is managed by the stack view
emailTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
// SetUp PasswordTextfield:
passswordTextField.backgroundColor = .white
passswordTextField.attributedPlaceholder = NSAttributedString(string: "Password", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
passswordTextField.textAlignment = NSTextAlignment.center
passswordTextField.layer.cornerRadius = 8
passswordTextField.layer.borderWidth = 1
passswordTextField.layer.borderColor = UIColor.lightGray.cgColor
// NO - it's already in the stack view
// self.view.addSubview(emailTextField)
// Set Only Width and Height - position is managed by the stack view
passswordTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
passswordTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
signInButton.setTitle("Sign In", for: [])
signInButton.backgroundColor = .blue
// Set Only Width and Height - position is managed by the stack view
signInButton.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
signInButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
}
Of course, using that layout - where you specified vertical spacing between the elements of 50-pts, and you've set explicit heights for each element, you'll likely find that it doesn't "fit quite right" across different devices / screen sizes.
So, as pointed out to you in your previous question here: Why is my VC displaced after changing the Simulator? AutoLayout - you probably want to change the stack view's Distribution to Equal Spacing and add a bottom constraint:
stackView.distribution = .equalSpacing
stackView.spacing = 0
stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20).isActive = true
That may or may not give you exactly what you want, but it's a starting point.
I think there is a problem about your constraint.
profilePicture.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
profilePicture.topAnchor.constraint(equalTo: view.topAnchor, constant: 110).isActive = true
are trying to center of the screen but they are inside of stack view. Also you have to give a static height to stack view on this scenario.
I am setting textfied and a button programmatically. The button is showing when we run the code but not textfield. is there any problem with constraints or any other please help.
let submitButton: UIButton = {
let btn = UIButton(type:.system)
btn.backgroundColor = .blue
btn.setTitle("Login", for: .normal)
btn.tintColor = .white
btn.layer.cornerRadius = 5
btn.clipsToBounds = true
btn.translatesAutoresizingMaskIntoConstraints = false
return btn
}()
let textBox: UITextView = {
let textView = UITextView()
textView.text = "we are learning iOs"
textView.font = UIFont.boldSystemFont(ofSize: 18)
textView.textAlignment = .center
textView.translatesAutoresizingMaskIntoConstraints = false
return textView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(textBox)
setupTexBoxLayout()
view.addSubview(submitButton)
setupSubmitBUttonLayout()
}
private func setupTexBoxLayout(){
textBox.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
textBox.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
textBox.widthAnchor.constraint(equalToConstant: 100).isActive = true
}
private func setupSubmitBUttonLayout(){
submitButton.topAnchor.constraint(equalTo: textBox.bottomAnchor, constant: 100).isActive = true
submitButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 100).isActive = true
}
}
I have checked your code and debug it.
You have not specified height for textview so it is not showing it.
You can check the below code. I have added height constraint to it and it is displaying your textfield.
If you do not specify a height for textfield then it will take 0 height by default.
private func setupTexBoxLayout(){
textBox.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
textBox.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
textBox.widthAnchor.constraint(equalToConstant: 300).isActive = true
textBox.heightAnchor.constraint(equalToConstant: 40).isActive = true
}
I am trying to get a group of buttons arranged within a stack view. However, when i use a for-each loop to do this, the buttons end up being positioned one on top of the other?
var stackView: UIStackView = {
let sView = UIStackView()
sView.axis = .vertical
sView.distribution = .fill
sView.alignment = .center
return sView
}()
var optionTitles = ["Sign in", "sign out"]
for title in optionTitles{
let btn = UIButton()
btn.setTitle(title, for: .normal)
btn.backgroundColor = optionColour.withAlphaComponent(0.6)
allButtons.append(btn)
stackView.addSubview(btn)
}
// Auto layout constraints
for button in allButtons{
button.translatesAutoresizingMaskIntoConstraints = false
button.heightAnchor.constraint(equalToConstant: optionHeight).isActive = true
button.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true
}
view.addSubview(stackView)
stackTopConstraint = stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
stackBottomConstraint = stackView.bottomAnchor.constraint(equalTo: view.topAnchor)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stackTopConstraint!.isActive = true
stackView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
2 things
1- You need to remove this
button.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true
2- Replace
stackView.addSubview(btn)
with
stackView.addArrangedSubview(btn)
You have:
stackTopConstraint = stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
stackBottomConstraint = stackView.bottomAnchor.constraint(equalTo: view.topAnchor)
You probably meant view.bottomAnchor in the second line. Surely you don't want to constraint the bottom of the stack view to the top of your view.