Stack Overflow Asked on December 5, 2021
I’m adding a very large UIView to a UIScrollView, however the scroll view does not scroll to show the whole subview.
When I add a label to the UIScrollView, it does scroll to show that label.
On the actual project I’m working on, I added many views within the scrollView and it is not scrolling at all. This is a simplified example to show my problem:
import UIKit
class ViewController: UIViewController {
let scrollView: UIScrollView = {
let scroll = UIScrollView()
scroll.backgroundColor = .blue
scroll.translatesAutoresizingMaskIntoConstraints = false
return scroll
}()
let viewDoesntWork: UIView = {
let view = UIView()
view.backgroundColor = .purple
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let labelWorks: UILabel = {
let label = UILabel()
label.text = "Why this work?"
label.backgroundColor = .green
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
// Add scrollView to view, 20 from edges of view on all sides
view.addSubview(scrollView)
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true
// OPTION 1 (does not work):
// Add viewDoesntWork to view, make it much bigger than the scrollView fits
scrollView.addSubview(viewDoesntWork)
viewDoesntWork.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 20).isActive = true
viewDoesntWork.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 20).isActive = true
viewDoesntWork.widthAnchor.constraint(equalToConstant: 1000).isActive = true
viewDoesntWork.heightAnchor.constraint(equalToConstant: 1000).isActive = true
// OPTION 2 (works):
// Add labelWorks to scrollView, and it does scroll to it.
// Uncomment this to see that work.
// scrollView.addSubview(labelWorks)
// labelWorks.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 1000).isActive = true
// labelWorks.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 1000).isActive = true
// labelWorks.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: -20).isActive = true
// labelWorks.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -20).isActive = true
}
}
As is, this does not scroll. But, if you comment out the specified section, it does.
Why is this? How can it make it such that adding subViews to the scrollView makes it scroll?
Thanks!
The answer of matt causes a [LayoutConstraints] problem in the console here is my simplified Answer
/*
I shortened and simplified your code, I also added some
explanations such that you could understand that's why the code will
seem long
*/
// let's call the viewDoesntWork view1
// first of all you didn't give a frame to the view1
/*
secondly you didn't set the content size(the content size is the
size of the scrollable area) of the scrollView!!
if the scrollView doesn't have a contentSize , it won't scroll
*/
/*
you don't need to set translatesAutoresizingMaskIntoConstraints =
false for labelWorks
Adding UIView to UIScrollView does not change the content size, you
have to set it manually
*/
import UIKit
class ViewController: UIViewController {
let scrollView: UIScrollView = {
let scroll = UIScrollView()
scroll.backgroundColor = .blue
scroll.translatesAutoresizingMaskIntoConstraints = false
return scroll
}()
let viewDoesntWork: UIView = {
let view = UIView()
view.backgroundColor = .purple
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let labelWorks: UILabel = {
let label = UILabel()
label.text = "Why this work?"
label.backgroundColor = .green
return label
}()
//In this function we set up the frame and other stuffs of the
//subviews
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// let's give it a content size
scrollView.contentSize = CGSize(width:view.frame.size.width , height: 1000)
viewDoesntWork.frame = CGRect(x: 20, y: 20,
width:view.frame.size.width , height: 800)
/*
viewDoesntWork.topAnchor.constraint(equalTo:
scrollView.topAnchor, constant: 20).isActive = true isn't
necessary anymore
since we set the y = 20 , the same goes for letfAnchor and x = 20
*/
/*
In my opinion , you don't need to set constraints for the size
of the viewDoesntWork
*/
labelWorks.frame = CGRect(x:view.center.x , y:
viewDoesntWork.frame.size.height + 20 + 40 , width:120,
height: 20)
// I added your label below the viewDoesntWork
/*
you don't need to set constraints, these are just some
calculations since you know the content size
*/
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
// Add scrollView to view, 20 from edges of view on all sides
view.addSubview(scrollView)
scrollView.addSubview(viewDoesntWork)
scrollView.addSubview(labelWorks)
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant:
20).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant:
20).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant:
-20).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant:
-20).isActive = true
}
}
Answered by Soren Nguia on December 5, 2021
The two things are not at all parallel. You have an example of what works, but in your other example you are not doing that, and that is why it doesn't work. Change:
viewDoesntWork.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 20).isActive = true
viewDoesntWork.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 20).isActive = true
viewDoesntWork.widthAnchor.constraint(equalToConstant: 1000).isActive = true
viewDoesntWork.heightAnchor.constraint(equalToConstant: 1000).isActive = true
To:
viewDoesntWork.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true
viewDoesntWork.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
viewDoesntWork.widthAnchor.constraint(equalToConstant: 1000).isActive = true
viewDoesntWork.heightAnchor.constraint(equalToConstant: 1000).isActive = true
viewDoesntWork.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0).isActive = true
viewDoesntWork.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true
Answered by matt on December 5, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP