0

I am trying to nest a stackView inside ScrollView to avoid constraint setting for individual views(3 labels and a ImageView). Without the StackView, things work well as individual views with constraints set to each of them inside a ScrollView.

Is it Ok to use a Vertical Stack inside a ScrollView? why is Distribution = 'Fill Proportionally' not rendering as intended?

The screenshot shows my constraints setting for ScrollView and StackView along with Attributes Inspector setting with Simulator output.

Screenshot of constraint settings in IB

udGlobal
  • 17
  • 7
  • Yes, you can put StackView inside a UIScrollView. If you can share your UI what you are trying to do. – nitin.agam Feb 15 '21 at 09:57
  • This is for learning purpose. I am trying to get NASA APOD Information. I have to display date of the Picture, Image that should be scrolled and zoomed, description that needs to scrolled and copyright information at the end. Should I use ScrollView with a nested contentView which has a nested vertical Stack View with all the views to render data as described above. – udGlobal Feb 15 '21 at 13:26
  • Ok, but I would suggest using UITableView for better controls. – nitin.agam Feb 15 '21 at 17:03
  • @UshaDesai - first, forget about `Fill Proportionally`, that's not what you want. You need to clarify what you mean by: *"the individual view content size is exceeding the intrinsic content size."* Show an image of what you are currently getting, and what you **want** to get. – DonMag Feb 16 '21 at 13:20
  • @UshaDesai - how do you want your imageView to be sized? Do you want it square (1:1 ratio)? Do you want it to match the image's original proportions? (I'm assuming you are filling in the labels and imageView dynamically...) – DonMag Feb 17 '21 at 12:58
  • @DonMag Yes,I want ImageView to match the image's original proportions ideally with both scrolls(Vertical and horizontal) enabled. Labels and ImageView are filled dynamically with the struct type populated using JSON decoder. – udGlobal Feb 19 '21 at 04:09

1 Answers1

0

Your comment: "I want ImageView to match the image's original proportions ideally with both scrolls(Vertical and horizontal) enabled." doesn't really make sense.

I'm guessing you pulled the data (in your screen capture) from https://apod.nasa.gov/apod/ap200116.html ... the image on that page is 4096 x 4088 pixels. If you want to show that with Vertical and Horizontal scrolling enabled, the entire screen will be covered by only a small portion of the image, and the user would need to scroll, scroll, scroll, scroll just to see the description.

More likely, what you probably want, is to choose an aspect ratio for your image view -- 16:10 is a common, reasonable ratio -- and set the imageView to Aspect Fit. It will look something like this:

enter image description here

So, here is how you'd want to layout your view controller in Storyboard:

enter image description here

When you have longer text, the description label will continue to expand vertically, and with enough text you'll get vertical scrolling.

You probably also want to embed the labels in views, so you can add some leading and trailing "padding" space for a better appearance.

The other option for your image view would be to give it a height constraint connected to an @IBOutlet. When you've downloaded the image, change the .constant for that constraint to match the aspect ratio of the new image. That would need to be done via code though - you can't do that directly in Storyboard (unless you'll always be getting the exact same size / aspect ratio images).


Edit

Here is one way to dynamically size the image view to match the aspect ratio of the downloaded image...

With the same Storyboard constraint settings, change the Priority on the aspect = 16:10 constraint to High (750).

When the view loads, the image view will match itself to the 16:10 aspect ratio.

Assuming you are using an async image download process, when the image has finished downloading:

// set the image
imageView.image = img
    
// get the aspect ratio
let m = img.size.height / img.size.width
    
// add new aspect ratio constraint to the image view
//  because this constraint will have (by default) a Priority of Required (1000),
//  it will "override" the Storyboard 16:10 constraint that has Priority: 750
self.imageView.heightAnchor.constraint(equalTo: self.imageView.widthAnchor, multiplier: m).isActive = true

// animate the size change
UIView.animate(withDuration: 0.3, animations: { [weak self] in
    guard let self = self else { return }
    self.view.layoutIfNeeded()
})

I put a working example here so you can try it out and inspect the layout and code: https://github.com/DonMag/UshaSample

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • I have given fixed width and height for imageView for now and used the downloaded UIImage to draw into UIGraphicsImageRenderer context to render a scaled-down version of that image. It works! I was not sure how to use Aspect Ratio and how to determine height `.constant'. I found a [https://stackoverflow.com/questions/26833627/with-auto-layout-how-do-i-make-a-uiimageviews-size-dynamic-depending-on-the-im] for such a scenario but yet to understand the code given in case 3 there. – udGlobal Feb 22 '21 at 13:42
  • @UshaDesai - you can dynamically change the height of the imageView to match the aspect ratio of the image. See the **Edit** to my answer. – DonMag Feb 22 '21 at 15:19
  • Thanks for both (Sorting out my StackView on Auto Layout and then imageView's dynamic height). One question: Are all downloaded images resized when they are significantly larger than the image view. What is the best technique to resize a large image other than the one I used above. – udGlobal Feb 22 '21 at 17:44
  • @UshaDesai - the imageView resizes the image for you. What is your goal? Are you caching the images on the device so you only download them once? Are you only ever displaying them at one size? Are you going to allow the user to view the image in a scroll view so they can "zoom in" on it? The answers to those questions will determine whether you want to resize the images or not. But -- that is all way beyond the scope of this "how do I get my stack view to work" question. – DonMag Feb 22 '21 at 18:07
  • By resizing above (using UIGraphicsImageRenderer) I meant to downsample the image. – udGlobal Feb 22 '21 at 18:19
  • Yeah, I started with StackView Issues. Now, StackView works fine with **Alignment:Fill, Distribution:Fill** and ImageView inside the stackView set to fixed width and height OR Aspect Ratio. But the **Distribution:Fill Proportional** still does not clear up Auto layout errors. – udGlobal Feb 22 '21 at 18:42
  • @UshaDesai - ***DO NOT USE FILL PROPORTIONAL***!!! Forget that even exists until you have experimented with it and completely understand how it works. Did you look at the GitHub example I posted? – DonMag Feb 22 '21 at 20:44
  • I looked at the GitHub example. That's really helpful. Thanks. I am learning a lot on Stackoverflow which otherwise would have taken days googling. What is the best way to master auto layout programmatically? – udGlobal Feb 23 '21 at 05:18
  • @UshaDesai - the best way to learn? Read the documentation... go through tutorials... take a class... pretty much the same way to learn anything. – DonMag Feb 23 '21 at 12:43