(Swift) StackView in ScrollView doesn't work - swift

I want to make a stackView in scrollView.
In stackView, I wanted to added some another stackViews, but it didn't work.
So, to simplify, I added some UIViews with addArrangedSubview() but it doesn't show anything.
How can I solve this? I spent a lot of my time...
scrollView = UIScrollView()
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scrollView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor),
scrollView.heightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.heightAnchor),
scrollView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
scrollView.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor)
])
var line1 = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 1000))
line1.backgroundColor = .blue
var line2 = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 1000))
line2.backgroundColor = .green
profile()
stackView = UIStackView()
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor)
])
stackView.addArrangedSubview(line1)
stackView.addArrangedSubview(line2)
stackView.updateConstraints()
stackView.setNeedsLayout()

I guess at the moment this code is running, the ViewControllers - view is still not set, so the width of your line1/2 will result in 0.
You should use auto layout to layout your views too.
var line1 = UIView()
line1.translatesAutoresizingMaskIntoConstraints = false
line1.backgroundColor = .blue
var line2 = UIView()
line1.translatesAutoresizingMaskIntoConstraints = false
line2.backgroundColor = .green
stackView = UIStackView(arrangedSubviews: [line1, line2])
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
line1.widthAnchor.constraint(equalTo: view.widthAnchor),
line1.heightAnchor.constraint(equalToConstant: 1000),
line2.widthAnchor.constraint(equalTo: view.widthAnchor),
line2.heightAnchor.constraint(equalToConstant: 1000),
])

Related

Why is my StackView not working? Elements are completely displaced

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.

Programatically created UIPageControl not showing

In my view hierarchy, I have a UIPageViewController (inside a container view). Underneath that is the UIPageControl and at the bottom is a stack view consisting of a text view and a button. I see the UIPageViewController and the stack view but not the UIPageControl. Any idea what I am doing wrong:
// Page view controller
introPageViewC = IntroPageViewC()
addChild(introPageViewC)
introPageViewC.view.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(introPageViewC.view)
NSLayoutConstraint.activate([
introPageViewC.view.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 0.0),
introPageViewC.view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0.0),
introPageViewC.view.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 0.0),
introPageViewC.view.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: 0.0),
])
introPageViewC.didMove(toParent: self)
// Page view control
introPageControl.currentPageIndicatorTintColor = UIColor.orange
introPageControl.pageIndicatorTintColor = UIColor.lightGray.withAlphaComponent(0.8)
view.addSubview(introPageControl)
introPageControl.translatesAutoresizingMaskIntoConstraints = false
introPageControl.topAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 10).isActive = true
introPageControl.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
// Stack view
view.addSubview(stackView)
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 30
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.topAnchor.constraint(equalTo: introPageControl.bottomAnchor, constant: 10).isActive = true
stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 40).isActive = true
stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -40).isActive = true
Expected output:
Edit:
Attempt at adding to the stack view:
var allViews = [UIView]()
// Adding to stackview
introPageControl.currentPageIndicatorTintColor = UIColor.orange
introPageControl.pageIndicatorTintColor = UIColor.lightGray.withAlphaComponent(0.8)
allViews.append(introPageControl)
nameTextField = UITextField(frame: CGRect(x: 0, y: 0, width: 120, height: 40))
nameTextField.placeholder = "Mealplan name"
Utilities.styleTextField(nameTextField)
nameTextField.setPadding()
allViews.append(nameTextField)
let nextButton = UIButton(type: .system)
nextButton.frame = CGRect(x: 20, y: 20, width: 100, height: 40)
nextButton.setTitle("Next", for: .normal)
nextButton.titleLabel?.textColor = .white
nextButton.titleLabel?.font = UIFont(name: "NexaBold", size: 16)
Utilities.styleDefaultButton(nextButton)
nextButton.addTarget(self, action: #selector(tapSubmit(_:)), for: .touchUpInside)
allViews.append(nextButton)
errorLabel.frame = CGRect(x: 20, y: 20, width: 100, height: 40)
errorLabel.font = UIFont(name: "NexaBold", size: 16)
errorLabel.textColor = .systemRed
errorLabel.textAlignment = .center
errorLabel.alpha = 0
allViews.append(errorLabel)
for eachView in allViews {
stackView.addArrangedSubview(eachView)
}
introPageControl.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
I believe you meant centerXAnchor?
I think you've got the topAnchor all wrong. Right now, it seems to be constrained to the bottom of the containerView plus 10, which is just off the screen. I think you meant to say -10.
introPageControl.topAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -10).isActive = true

Nested UIStackView child in UIScrollView does not stretch to fill

I have a UIStackView.
I have added some views.
The last view should be at to the bottom of the screen. To achieve this I have added a view that acts as a spacer, I have set a height on the first and last view with the idea that the middle view stretches to fill the space.
This works.
let topView = UIView(frame: .zero)
topView.withSize(.init(width: 0, height: 100))
topView.backgroundColor = .lightGray
let spacerView = UIView(frame: .zero)
spacerView.backgroundColor = .darkGray
let bottomView = UIView(frame: .zero)
bottomView.withSize(.init(width: 0, height: 200))
bottomView.backgroundColor = .lightGray
let stackView = UIStackView()
stackView.axis = .vertical
stackView.alignment = .fill
stackView.spacing = 0
stackView.distribution = .fill
addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
stackView.topAnchor.constraint(equalTo: topAnchor),
stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
])
[topView, spacerView, bottomView].forEach { stackView.addArrangedSubview($0) }
I have a scenario however where the screen size may be smaller than the size of the views.
I am trying to embed my UIStackView in a UIScrollView however when I do this, the spacer view no longer stretches itself. It is as if the height is now zero. (I have added spacing to show the top and bottom views)
let topView = UIView(frame: .zero)
topView.withSize(.init(width: 0, height: 100))
topView.backgroundColor = .lightGray
let spacerView = UIView(frame: .zero)
spacerView.backgroundColor = .darkGray
let bottomView = UIView(frame: .zero)
bottomView.withSize(.init(width: 0, height: 200))
bottomView.backgroundColor = .lightGray
let scrollView = UIScrollView(frame: .zero)
addSubviews(scrollView)
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
scrollView.topAnchor.constraint(equalTo: topAnchor),
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
let stackView = UIStackView()
stackView.axis = .vertical
stackView.alignment = .fill
stackView.spacing = 8
stackView.distribution = .fill
scrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// Attaching the content's edges to the scroll view's edges
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
// Satisfying size constraints
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
[topView, spacerView, bottomView].forEach { stackView.addArrangedSubview($0) }
I would expect in this case my UIStackView to still fill the view and only be scrollable if a child view causes it to grow in height beyond the visible bounds of the view.
Use a UITableView with a UICollectionView as a Footer.
You can find a tutorial here:
https://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell-in-swift/
This is for adding a collectionView as a header but works the same for footer.
private let tableView: UITableView = {
let view = UITableView(frame: .zero, style: .plain)
view.translatesAutoresizingMaskIntoConstraints = false
view.estimatedRowHeight = 44
view.rowHeight = UITableView.automaticDimension
view.keyboardDismissMode = .interactive
view.tableFooterView = //Your Custom View with CollectionView here
return view
}()

Programmatically created ScrollView is not working

i still don't get the hang of UIScrollView...
i want to create one add it to a container and add a StackView to it:
let scroll = UIScrollView()
scroll.contentSize = CGSize(width: stackWidth, height: stackHeight)
bottomContainer.addSubview(scroll)
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .center
stack.distribution = .equalSpacing
scroll.addSubview(stack)
stack.translatesAutoresizingMaskIntoConstraints = false
scroll.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scroll.topAnchor.constraint(equalTo: bottomContainer.topAnchor, constant: 25),
scroll.bottomAnchor.constraint(equalTo: bottomContainer.bottomAnchor, constant: 25),
scroll.leadingAnchor.constraint(equalTo: bottomContainer.leadingAnchor),
scroll.trailingAnchor.constraint(equalTo: bottomContainer.trailingAnchor),
scroll.widthAnchor.constraint(equalToConstant: stackWidth),
scroll.heightAnchor.constraint(equalToConstant: stackWidth),
stack.topAnchor.constraint(equalTo: scroll.topAnchor),
stack.bottomAnchor.constraint(equalTo: scroll.bottomAnchor),
stack.leadingAnchor.constraint(equalTo: scroll.leadingAnchor),
stack.widthAnchor.constraint(equalToConstant: stackWidth),
])
bottomContainer is created in Storyboard.
stackHeight is calculated to be 50 less than the height of bottomContainer and stackWidth is variable but even if gets greater than the bottomContainer it doesn't scroll. Thanks for any help
Try this
var screenHeight = UIScreen.main.bounds.height
var screenWidth = UIScreen.main.bounds.width
let scroll = UIScrollView()
scroll.contentSize = CGSize(width: screenWidth, height: screenHeight)
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .center
stack.distribution = .equalSpacing
scroll.addSubview(stack)
stack.translatesAutoresizingMaskIntoConstraints = false
scroll.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
scroll.topAnchor.constraint(equalTo: bottomContainer.topAnchor, constant: 25),
scroll.bottomAnchor.constraint(equalTo: bottomContainer.bottomAnchor, constant: 25),
scroll.leadingAnchor.constraint(equalTo: bottomContainer.leadingAnchor),
scroll.trailingAnchor.constraint(equalTo: bottomContainer.trailingAnchor),
scroll.widthAnchor.constraint(equalToConstant: stackWidth),
scroll.heightAnchor.constraint(equalToConstant: stackWidth),
stack.topAnchor.constraint(equalTo: scroll.topAnchor),
stack.bottomAnchor.constraint(equalTo: scroll.bottomAnchor),
stack.leadingAnchor.constraint(equalTo: scroll.leadingAnchor),
stack.widthAnchor.constraint(equalToConstant: stackWidth),
])
scroll.contentSize = CGSize(width: stackWidth, height: stackHeight)
bottomContainer.addSubview(scroll)

UIStackView - force label to be tight and view to be as wide as possible

I have UIStackView
let sv = UIStackView()
sv.axis = .horizontal
sv.distribution = .fillProportionally
sv.spacing = 2.0
sv.translatesAutoresizingMaskIntoConstraints = false
Now I have added two elements (UIView and UILabel). If I run app, I have see something like this:
| Content (UIView)| Content (UILabel)|
But I want it like this:
| Content (UIView) | Content (UILabel)|
How to do this?
My code for setting stack view:
let lb = UILabel()
lb.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.light)
lb.lineBreakMode = .byTruncatingTail
lb.numberOfLines = 2
lb.textAlignment = .right
lb.backgroundColor = UIColor.red
lb.adjustsFontSizeToFitWidth = true
let v = UIView()
stackView.addArrangedSubview(v)
stackView.addArrangedSubview(lb)
self.contentView.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 2),
stackView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 10),
stackView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -10),
stackView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -2)
])
Just set content compression resistance priority to 1000 for view's horizontal axis
v.setContentCompressionResistancePriority(.required, for: .horizontal)
... then your view should take as much space as it needs because it won't be compressed