I have the following scrollview but it's not scrolling. Can someone please help?
private func setupUI() {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
view.addSubview(scrollView)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
let contentView = UIView()
contentView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(contentView)
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor)
])
let closeButton = UIButton(type: .custom)
closeButton.setBackgroundImage(UIImage(named: "close-x"), for: .normal)
closeButton.addTarget(self, action: #selector(closeTapped), for: .touchUpInside)
closeButton.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(closeButton)
let imageView1 = UIImageView()
imageView1.image = UIImage(named: "freetrialtop")
imageView1.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(imageView1)
let overlayButton = UIButton(type: .custom)
overlayButton.setImage(UIImage(named: "freetrialbtn"), for: .normal)
overlayButton.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(overlayButton)
let titleLabel = UILabel()
titleLabel.text = "Try Test PRO"
titleLabel.font = UIFont(name: "WorkSans-SemiBold", size: 28)
titleLabel.textColor = UIColor(red: 0.15, green: 0.16, blue: 0.20, alpha: 1.00)
titleLabel.textAlignment = .center
titleLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(titleLabel)
let subtitleLabel = UILabel()
subtitleLabel.text = "7 days free, then $89.99/per year"
subtitleLabel.font = UIFont(name: "WorkSans-Regular", size: 15)
subtitleLabel.textAlignment = .center
subtitleLabel.textColor = .gray
subtitleLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(subtitleLabel)
let trialLabel = UILabel()
trialLabel.text = "How your trial works:"
trialLabel.font = UIFont(name: "WorkSans-SemiBold", size: 14)
trialLabel.textAlignment = .left
trialLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(trialLabel)
let imageView2 = UIImageView()
imageView2.image = UIImage(named: "freetrialline")
imageView2.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(imageView2)
let priceLabel = UILabel()
priceLabel.text = "7 days free, then $89.99/per year"
priceLabel.font = UIFont(name: "WorkSans-Regular", size: 14)
priceLabel.textAlignment = .center
priceLabel.textColor = .gray
priceLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(priceLabel)
let weeklyPriceLabel = UILabel()
weeklyPriceLabel.text = "Only $1.73 / week"
weeklyPriceLabel.font = UIFont(name: "WorkSans-SemiBold", size: 24)
weeklyPriceLabel.textAlignment = .center
weeklyPriceLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(weeklyPriceLabel)
let subscribeButton = UIButton(type: .custom)
subscribeButton.setImage(UIImage(named: "freetrialbtn1"), for: .normal)
subscribeButton.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(subscribeButton)
let cancelStackView = UIStackView()
cancelStackView.axis = .horizontal
cancelStackView.alignment = .center
cancelStackView.spacing = 8
cancelStackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(cancelStackView)
let cancelLabel = UILabel()
cancelLabel.text = "Cancel anytime. Secure with App Store"
cancelLabel.font = UIFont(name: "Inter-Regular", size: 14)
cancelLabel.textAlignment = .center
cancelLabel.textColor = .darkGray
cancelLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(cancelLabel)
let cancelImage = UIImageView(image: UIImage(systemName: "checkmark.shield"))
cancelImage.tintColor = .gray
cancelImage.setContentHuggingPriority(.defaultHigh, for: .horizontal)
cancelImage.setContentCompressionResistancePriority(.required, for: .horizontal)
cancelStackView.addArrangedSubview(cancelImage)
cancelStackView.addArrangedSubview(cancelLabel)
let todayLabel = UILabel()
todayLabel.text = "Today - Free trial starts"
todayLabel.font = UIFont(name: "WorkSans-SemiBold", size: 16)
todayLabel.textAlignment = .left
todayLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(todayLabel)
let todayDetailLabel = UILabel()
todayDetailLabel.text = "Enjoy full access free for 7 days."
todayDetailLabel.font = UIFont(name: "WorkSans-Regular", size: 12)
todayDetailLabel.textAlignment = .left
todayDetailLabel.textColor = .gray
todayDetailLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(todayDetailLabel)
let reminderLabel = UILabel()
reminderLabel.text = "\(getFutureDate(daysAhead: 5)) - Email reminder"
reminderLabel.font = UIFont(name: "WorkSans-SemiBold", size: 16)
reminderLabel.textAlignment = .left
reminderLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(reminderLabel)
let reminderDetailLabel = UILabel()
reminderDetailLabel.text = "We’ll let you know when your trial is ending."
reminderDetailLabel.font = UIFont(name: "WorkSans-Regular", size: 12)
reminderDetailLabel.textAlignment = .left
reminderDetailLabel.textColor = .gray
reminderDetailLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(reminderDetailLabel)
let memberLabel = UILabel()
memberLabel.text = "\(getFutureDate(daysAhead: 7)) - Become a member"
memberLabel.font = UIFont(name: "WorkSans-SemiBold", size: 16)
memberLabel.textAlignment = .left
memberLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(memberLabel)
let memberDetailLabel = UILabel()
memberDetailLabel.text = "Your trial ends unless canceled. Enjoy!"
memberDetailLabel.font = UIFont(name: "WorkSans-Regular", size: 12)
memberDetailLabel.textAlignment = .left
memberDetailLabel.textColor = .gray
memberDetailLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(memberDetailLabel)
NSLayoutConstraint.activate([
imageView1.topAnchor.constraint(equalTo: contentView.topAnchor),
imageView1.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
imageView1.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
imageView1.heightAnchor.constraint(equalToConstant: 205),
closeButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10),
closeButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
overlayButton.centerXAnchor.constraint(equalTo: imageView1.centerXAnchor),
overlayButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10),
overlayButton.widthAnchor.constraint(equalToConstant: 243),
overlayButton.heightAnchor.constraint(equalToConstant: 66),
titleLabel.topAnchor.constraint(equalTo: overlayButton.bottomAnchor, constant: 20),
titleLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 5),
subtitleLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
trialLabel.topAnchor.constraint(equalTo: imageView1.bottomAnchor, constant: 20),
trialLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
imageView2.topAnchor.constraint(equalTo: trialLabel.bottomAnchor, constant: 25),
imageView2.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
imageView2.widthAnchor.constraint(equalToConstant: 32),
imageView2.heightAnchor.constraint(equalToConstant: 212),
todayLabel.topAnchor.constraint(equalTo: imageView2.topAnchor),
todayLabel.leadingAnchor.constraint(equalTo: imageView2.trailingAnchor, constant: 10),
todayDetailLabel.topAnchor.constraint(equalTo: todayLabel.bottomAnchor, constant: 5),
todayDetailLabel.leadingAnchor.constraint(equalTo: imageView2.trailingAnchor, constant: 10),
reminderLabel.topAnchor.constraint(equalTo: todayDetailLabel.bottomAnchor, constant: 40),
reminderLabel.leadingAnchor.constraint(equalTo: imageView2.trailingAnchor, constant: 10),
reminderDetailLabel.topAnchor.constraint(equalTo: reminderLabel.bottomAnchor, constant: 5),
reminderDetailLabel.leadingAnchor.constraint(equalTo: imageView2.trailingAnchor, constant: 10),
memberLabel.topAnchor.constraint(equalTo: reminderDetailLabel.bottomAnchor, constant: 40),
memberLabel.leadingAnchor.constraint(equalTo: imageView2.trailingAnchor, constant: 10),
memberDetailLabel.topAnchor.constraint(equalTo: memberLabel.bottomAnchor, constant: 5),
memberDetailLabel.leadingAnchor.constraint(equalTo: imageView2.trailingAnchor, constant: 10),
priceLabel.topAnchor.constraint(equalTo: imageView2.bottomAnchor, constant: 50),
priceLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
weeklyPriceLabel.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: 5),
weeklyPriceLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
subscribeButton.topAnchor.constraint(equalTo: weeklyPriceLabel.bottomAnchor, constant: 20),
subscribeButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
subscribeButton.widthAnchor.constraint(equalToConstant: 335),
subscribeButton.heightAnchor.constraint(equalToConstant: 48),
cancelStackView.topAnchor.constraint(equalTo: subscribeButton.bottomAnchor, constant: 10),
cancelStackView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor)
])
If we take your code and make only one change:
contentView.backgroundColor = .green
and run it, we'd expect to see a big, green background... correct?
Give it a try -- no green!
You have added a bunch of views, buttons, labels, etc as subviews to contentView
, but you have not defined a bottom constraint for that view.
Add this line at the very end of your constraints block:
cancelStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0.0)
You should now see the green background.
If you still do not get scrolling, it's because there is not enough height to need to scroll. For example, your code on an iPhone 15 Pro - all the UI elements fit without scrolling.
If we change the top anchor of your cancelStackView
from:
cancelStackView.topAnchor.constraint(equalTo: subscribeButton.bottomAnchor, constant: 10),
to:
cancelStackView.topAnchor.constraint(equalTo: subscribeButton.bottomAnchor, constant: 150),
it will "push" that element down far enough that we need to scroll ... and we will be able to scroll.