-2

I'm working on an app that uses a Scrollview -> StackView -> button, imageview, textview view hierarchy. (I'm building the view programmatically rather than using storyboard. I'm using a scrollview as the top view so it will handle pinch/zoom for me.

If I start the app in portrait mode, things layout like I want. If I then rotate to landscape, the layout does not adjust properly. Same for starting in landscape and then rotating to portrait -- the layout does not adjust correctly.

Here is the layout if I start in portrait. Next image is when I rotate to landscape.

enter image description here

enter image description here

enter image description here

enter image description here

Here is snippets of sample code.

scrollView.frame = view.bounds
scrollView.delegate = self
scrollView.zoomScale = 1.0
scrollView.maximumZoomScale = 5.0
scrollview.minimumZoomScale = 0.5
scrollView.frame = view.bounds

imageView.backgroundColor = .systemGreen
imageView.image = UIImage(systemName: "bell")
imageView.contentMode = .scaleAspectFit

textView.text = "This is a bunch of text blah blah"

stackView.addArrangedSubview(imageView)
stackView.addArrangedSubview(label)
stackView.addArrangedSubview(textView)
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 20

scrollView.addSubview(stackView)
view.addSubview(scrollView)

Any pointers and suggestions would be greatly appreciated.

I'd like to be able to properly handle device rotation. Images show rotation results.

rdk
  • 91
  • 1
  • 8
  • 1
    Unclear what you expect / want to happen on rotation. You have no rotation code so the layout doesn't change. – matt Apr 26 '23 at 20:27
  • Hey! In theory, if I rotate from portrait to landscape, I want the layout to adjust to what it looks like if I start fresh in landscape mode. Vice versa going from landscape to portrait. – rdk Apr 26 '23 at 20:29
  • I have been playing with various constraint code all day but it doesnt seem to help much. I guess I'm asking how to set constraints to make this work. Thanks. – rdk Apr 26 '23 at 20:30
  • I've played with overriding viewWillTransition() but that doesnt reliably seem to get called. Also, I'm not sure what I would do in that function. I've also been searching and watching various YT videos on setting up stackview constraints. No luck. :( – rdk Apr 26 '23 at 20:31
  • 1
    You do not need `viewWillTransition` or any other similar method. Setup the constraints once when you create the stack view and you are done. Update your question with your attempts to setup constraints. – HangarRash Apr 26 '23 at 23:42
  • Here's a simple example. https://stackoverflow.com/a/55834371/341994 – matt Apr 26 '23 at 23:51
  • Matt, thank you. I don't want to change the axis though. I'll update question with constraint attempts. – rdk Apr 27 '23 at 00:06
  • 1
    You still have said nothing about what you want to have happen on rotation. – matt Apr 27 '23 at 02:24

1 Answers1

2

Your code and your goal are a little bit confused, if I understand well you can do it with autoLayout, take a look to my example below:

class YourViewController: UIViewController {

// Declare your constant
let scrollView = UIScrollView()
let imageView = UIImageView()
let textView = UITextView()
let label = UILabel()
let myBGView = UIView()
let stackView = UIStackView()

override func viewDidLoad() {
    super.viewDidLoad()
    
    view.backgroundColor = .red
    setupUI()
    setupConstraints()
}

// Setup UI elements
fileprivate func setupUI() {
    myBGView.backgroundColor = .systemYellow
    label.backgroundColor = .systemBlue
    label.text = "Hello World"
    label.textAlignment = .center
    label.font = .systemFont(ofSize: 16, weight: .bold)
    
    textView.backgroundColor = .white
    textView.isUserInteractionEnabled = false
    textView.text = "This is a bunch of text\nMore text on this line\nEven more text"
    
    scrollView.backgroundColor = .red
    scrollView.zoomScale = 1.0
    scrollView.maximumZoomScale = 5.0
    scrollView.minimumZoomScale = 0.5
    
    imageView.backgroundColor = .systemGreen
    imageView.image = UIImage(systemName: "bell")
    imageView.contentMode = .scaleAspectFit
    
    stackView.axis = .vertical
    stackView.distribution = .fillEqually
    stackView.spacing = 20
    stackView.addArrangedSubview(imageView)
    stackView.addArrangedSubview(label)
    stackView.addArrangedSubview(textView)
    
    view.addSubview(scrollView)
    scrollView.addSubview(myBGView)
    myBGView.addSubview(stackView)
}

//setup constraints

fileprivate func setupConstraints() {
    
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    myBGView.translatesAutoresizingMaskIntoConstraints = false
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    
    myBGView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
    myBGView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    myBGView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
    myBGView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
    myBGView.heightAnchor.constraint(equalToConstant: 299).isActive = true
    
    stackView.topAnchor.constraint(equalTo: myBGView.topAnchor, constant: -1).isActive = true
    stackView.leadingAnchor.constraint(equalTo: myBGView.leadingAnchor).isActive = true
    stackView.trailingAnchor.constraint(equalTo: myBGView.trailingAnchor).isActive = true
    stackView.bottomAnchor.constraint(equalTo: myBGView.bottomAnchor).isActive = true
  }
}

This is the result:

enter image description here

Landscape rotation

enter image description here

Simply open a new project and paste the code, if I correctly understand your question this is a good start point for you.

Fabio
  • 5,432
  • 4
  • 22
  • 24
  • Thank you!!!!! I came to similar conclusion last night after more googling. I also figured out that I should set textView.scrollingEnabled = false. Since text is already in a scrollView, no need to have two levels of scrolling. – rdk Apr 27 '23 at 12:52
  • @Fabio This may be a bit pedantic but you have a `setupUI` method that has code that does some constraint related setup and you have a `setupConstraints` method that has code that does some UI related setup. Personally I would have the setting of `translatesAutoresizingMaskIntoConstraints` in the `setupConstraints` method and I would have the use of `addSubview` and the creation of the stack view in the `setupUI` method. – HangarRash Apr 27 '23 at 15:16
  • 2
    @rdk I update my answer, take a look – Fabio Apr 27 '23 at 15:43