Swift ScrollView Layout Issue With PageController and Images iOS - ios

I can't figure out how to set constraints for a scrollView with an imageView inside.
I am using the scrollView with a pageConroller to swipe thru a bunch of images.
See my layout in the picture below.
// Code for imageView
for index in 0..<drinksImagesArray.count {
frame.origin.x = scrollView.frame.size.width * CGFloat(index)
frame.size = scrollView.frame.size
let imageView = UIImageView(frame: frame)
imageView.contentMode = .scaleAspectFit
imageView.image = UIImage(named: imagesArray[index].name)
self.scrollView.addSubview(imageView)
}
scrollView.contentSize = CGSize(width: scrollView.frame.size.width * CGFloat(imagesArray.count), height: scrollView.frame.size.height)
scrollView.delegate = self
Any suggestions? Thank you!
Layout

You will have much better luck using auto-layout --- it can handle all of the frame sizes and .contentSize for you.
Here's a quick example - it uses a view controller with a scroll view added in Storyboard, so it should be pretty easy for you to integrate with your code:
class ScrollingImagesViewController: UIViewController {
#IBOutlet var scrollView: UIScrollView!
var drinksImagesArray: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
// however you're populating your array...
drinksImagesArray = [
"drink1",
"drink2",
"drink3",
// etc...
]
// create a horizontal stack view
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
stack.spacing = 0
// add the stack view to the scroll view
stack.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(stack)
// use scroll view's contentLayoutGuide for content constraints
let svCLG = scrollView.contentLayoutGuide
NSLayoutConstraint.activate([
// stack view constrained Top / Bottom / Leading / Trailing of scroll view CONTENT guide
stack.topAnchor.constraint(equalTo: svCLG.topAnchor),
stack.bottomAnchor.constraint(equalTo: svCLG.bottomAnchor),
stack.leadingAnchor.constraint(equalTo: svCLG.leadingAnchor),
stack.trailingAnchor.constraint(equalTo: svCLG.trailingAnchor),
// stack view height == scroll view FRAME height
stack.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor),
])
// create image views and add them to the stack view
drinksImagesArray.forEach { imgName in
let v = UIImageView()
v.backgroundColor = .lightGray
v.contentMode = .scaleAspectFit
// make sure we load a valid image
if let img = UIImage(named: imgName) {
v.image = img
}
stack.addArrangedSubview(v)
}
// stack distribution is set to .fillEqually, so we only need to set the
// width constraint on the first image view
// unwrap it
if let firstImageView = stack.arrangedSubviews.first {
firstImageView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor).isActive = true
}
}
}
Edit
After reviewing your Storyboard...
Auto-layout doesn't seem to like it when you add a UINavigationBar and a UIToolbar and a UIScrollView as subviews. In particular, it appears to confuse the scroll view's frame related constraints.
The fix is to first add constraints for your scroll view:
Top to Navigation Bar Bottom
Bottom to Page Control Top
Leading and Trailing to safe-area
Storyboard / Interface builder will complain that the scroll view is not configured properly. You can either ignore that, or select the scroll view and set Ambiguity to Never Verify:
Then, in your view controller class, we need to create a height constraint for the stack view we're adding to the scroll view, and set that height constant in viewDidLayoutSubviews().
Here's the full code:
//
// WasserhaushaltViewController.swift
// deSynthTheOceans
//
// Created by robinsonhus0 on 24.03.20.
// Copyright © 2020 robinsonhus0. All rights reserved.
//
import UIKit
import AVFoundation
import Charts
import FSCalendar
import HealthKit
struct WasserSpeicher: Codable {
let wassermenge: Double
let speicherdatum: String
let speicherStelle: Double
}
class WasserhaushaltViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var diagrammView: UIView!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
let drinksImagesArray = ["tapWater", "water", "milk", "cola", "coffee", "tea", "juice", "beer"]
var imageIndex = Int()
struct Drinks {
var name: String
var tagesMengeFactor: Double
var gesamtMengeFactor: Double
}
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
var pageNumber = CGFloat()
#IBOutlet weak var todaysWaterConsumptionLabel: UILabel!
#IBOutlet weak var waterGoalProgress: UIProgressView!
#IBOutlet weak var waterGoalLabel: UILabel!
#IBOutlet weak var wasserMengeStepper: UIStepper!
#IBOutlet weak var motivationTextView: UITextView!
#IBOutlet weak var wasserglasButton: UIBarButtonItem!
#IBOutlet weak var kleineFlascheButton: UIBarButtonItem!
#IBOutlet weak var grosseFlascheButton: UIBarButtonItem!
#IBOutlet weak var overAllWaterConsumptionLabel: UILabel!
// added
let scrollingImagesStackView = UIStackView()
var stackHeightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
pageControl.numberOfPages = drinksImagesArray.count
setupDrinkImages()
}
func setupDrinkImages() {
// set stack view properties
scrollingImagesStackView.axis = .horizontal
scrollingImagesStackView.alignment = .fill
scrollingImagesStackView.distribution = .fillEqually
scrollingImagesStackView.spacing = 0
// add the stack view to the scroll view
scrollingImagesStackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(scrollingImagesStackView)
// use scroll view's contentLayoutGuide for content constraints
let svCLG = scrollView.contentLayoutGuide
NSLayoutConstraint.activate([
// stack view constrained Top / Bottom / Leading / Trailing of scroll view CONTENT guide
scrollingImagesStackView.topAnchor.constraint(equalTo: svCLG.topAnchor),
scrollingImagesStackView.bottomAnchor.constraint(equalTo: svCLG.bottomAnchor),
scrollingImagesStackView.leadingAnchor.constraint(equalTo: svCLG.leadingAnchor),
scrollingImagesStackView.trailingAnchor.constraint(equalTo: svCLG.trailingAnchor),
])
// create the stack view height constraint - it will be updated in viewDidLayoutSubviews
stackHeightConstraint = scrollingImagesStackView.heightAnchor.constraint(equalToConstant: 0)
stackHeightConstraint.isActive = true
// create image views and add them to the stack view
drinksImagesArray.forEach { imgName in
let v = UIImageView()
v.backgroundColor = .orange
v.contentMode = .scaleAspectFit
// make sure we load a valid image
if let img = UIImage(named: imgName) {
v.image = img
}
scrollingImagesStackView.addArrangedSubview(v)
}
// stack distribution is set to .fillEqually, so we only need to set the
// width constraint on the first image view
// unwrap it
if let firstImageView = scrollingImagesStackView.arrangedSubviews.first {
firstImageView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor).isActive = true
}
scrollView.delegate = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// since we have a UINavigationBar and a UIToolBar in the view hierarchy,
// we need to set this here
// Note: if the view size changes
// stack view height == scroll view FRAME height
stackHeightConstraint.constant = scrollView.frame.height
}
// func setupDrinkImages() {
// for index in 0..<drinksImagesArray.count {
// frame.origin.x = scrollView.frame.size.width * CGFloat(index)
// frame.size = scrollView.frame.size
//
// let imageView = UIImageView(frame: frame)
// imageView.contentMode = .scaleAspectFit
// imageView.image = UIImage(named: drinksImagesArray[index])
// self.scrollView.addSubview(imageView)
// }
// scrollView.contentSize = CGSize(width: scrollView.frame.size.width * CGFloat(drinksImagesArray.count), height: scrollView.frame.size.height)
// scrollView.delegate = self
// }
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
pageControl.currentPage = Int(pageNumber)
}
}
Your (modified) Storyboard is too big to add here... if you have any trouble with the changes mentioned above, here it is: https://pastebin.com/2Q1uFUgL

Related

IOS Swift4 Not able to scroll a ScrollView

I hv been trying to make a scrollview scroll, just to the extent that the scrollview is supposed to show. However, I am not able to. This is my code.
func setupMainView() {
// This is where the image view and other UIViews which are supposed to go in the contentview are set up
self.setupImagesView()
self.setupView1()
self.setupView2()
self.setupView3()
self.setupView4()
self.scrollView = UIScrollView()
self.scrollView.backgroundColor = UIColor.white
self.view.addSubview(self.scrollView)
self.automaticallyAdjustsScrollViewInsets = false
self.scrollView.contentInset = UIEdgeInsets.zero
self.scrollView.scrollIndicatorInsets = UIEdgeInsets.zero;
self.contentView = UIView()
self.scrollView.layer.masksToBounds = false
self.scrollView.backgroundColor = UIColor.white
self.scrollView.layer.borderWidth = 0
self.scrollView.layer.borderColor = UIColor.white.cgColor
self.view.addSubview(scrollView)
self.contentView.addSubview(imagesScrollView)
self.contentView.addSubview(view1)
self.contentView.addSubview(view2)
self.contentView.addSubview(view3)
self.contentView.addSubview(view4)
self.scrollView.addSubview(contentView)
self.scrollView.contentInset = UIEdgeInsets.zero
self.scrollView.scrollIndicatorInsets = UIEdgeInsets.zero;
var scrollViewHeight:CGFloat = 0.0;
for _ in self.scrollView.subviews {
scrollViewHeight += view.frame.size.height
}
var newHeight = scrollViewHeight * 1.1 + offset + 100
scrollView.contentSize = CGSize(width:screenWidth, height:newHeight)
scrollView.reloadInputViews()
}
The views are getting loaded etc, but I am not manage the scroll. It somehow either too little or too much.
Now, I tried setting the height of contentSize to scrollViewHeight and double of that etc. What I notice is that there is no predictability of how much it will scroll. Change from 1.1 to 1.6 .. there is too much whitescreen below the views, change it to 1.1 or 1.2 it does not even scroll to the bottom.
Note, everything has been set up programmatically, without storyboard etc.
Also note that I need to support all IOS devices with version > 10.
Am a little lost here. What am I doing wrong?
This is a very old way of configuring a scroll view - you should be using auto-layout.
And, you're doing a number of things wrong...
First, we'll assume you are setting frames of the various subviews in code you haven't shown.
However, the code you have shown creates a scrollView and adds it to self.view -- but you never set the frame of the scroll view.
Also, this part of your code:
for _ in self.scrollView.subviews {
scrollViewHeight += view.frame.size.height
}
you've added several views as subviews of contentView, then added contentView as the only subview of scrollView.
And... you are trying to increment scrollViewHeight by the height of your root view instead of the height of the scrollView's subviews.
So, scrollViewHeight will only be the height of self.view.
What you probably want to do is sum the heights of contentView.subviews:
var contentViewHeight: CGFloat = 0
for v in contentView.subviews {
contentViewHeight += v.frame.height
}
contentView.frame.size.height = contentViewHeight
then set the scrollView's contentSize.height to the height of contentView's frame.
Here is a very, very basic example, using explicitly set frame sizes -- again, though, you should start using auto-layout:
class SimpleScrollViewController: UIViewController {
var imagesScrollView: UIView!
var view1: UIView!
var view2: UIView!
var view3: UIView!
var view4: UIView!
var contentView: UIView!
var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
setupMainView()
}
func setupMainView() {
// This is where the image view and other UIViews which are supposed to go in the contentview are set up
self.setupImagesView()
self.setupView1()
self.setupView2()
self.setupView3()
self.setupView4()
self.scrollView = UIScrollView()
// let's use a color other than white so we can see the frame of the scrollView
self.scrollView.backgroundColor = UIColor.cyan
self.view.addSubview(self.scrollView)
self.automaticallyAdjustsScrollViewInsets = false
self.scrollView.contentInset = UIEdgeInsets.zero
self.scrollView.scrollIndicatorInsets = UIEdgeInsets.zero;
self.contentView = UIView()
self.contentView.backgroundColor = UIColor.lightGray
self.scrollView.layer.masksToBounds = false
self.scrollView.layer.borderWidth = 0
self.scrollView.layer.borderColor = UIColor.white.cgColor
self.view.addSubview(scrollView)
self.contentView.addSubview(imagesScrollView)
self.contentView.addSubview(view1)
self.contentView.addSubview(view2)
self.contentView.addSubview(view3)
self.contentView.addSubview(view4)
self.scrollView.addSubview(contentView)
self.scrollView.contentInset = UIEdgeInsets.zero
self.scrollView.scrollIndicatorInsets = UIEdgeInsets.zero;
var contentViewHeight: CGFloat = 0
for v in contentView.subviews {
contentViewHeight += v.frame.height
}
contentView.frame.size.height = contentViewHeight
// don't know what you're doing here....
//scrollView.reloadInputViews()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// here is where you know the frame of self.view
// so, make the scroll view cover the entire view
scrollView.frame = view.frame
// now, make contentView width equal to scrollView width
contentView.frame.size.width = scrollView.frame.size.width
// set the scrollView's content size
scrollView.contentSize = contentView.frame.size
}
func setupImagesView() -> Void {
imagesScrollView = UIView()
imagesScrollView.backgroundColor = .red
imagesScrollView.frame = CGRect(0, 0, 300, 100)
}
func setupView1() -> Void {
view1 = UIView()
view1.backgroundColor = .green
view1.frame = CGRect(20, imagesScrollView.frame.maxY, 300, 200)
}
func setupView2() -> Void {
view2 = UIView()
view2.backgroundColor = .blue
view2.frame = CGRect(40, view1.frame.maxY, 300, 250)
}
func setupView3() -> Void {
view3 = UIView()
view3.backgroundColor = .yellow
view3.frame = CGRect(60, view2.frame.maxY, 200, 275)
}
func setupView4() -> Void {
view4 = UIView()
view4.backgroundColor = .orange
view4.frame = CGRect(80, view3.frame.maxY, 200, 100)
}
}
If I remember correctly you need to in order for scroll view to work you need to implement a couple of delegate methods. You also need a couple of properties set.
contentSize is one
and I think min and max size
see: https://developer.apple.com/documentation/uikit/uiscrollviewdelegate
also see Stanford University's
Paul Hagarty Developing IOS 11 apps with swift episode 9 for loads of information on UIScrollView
https://www.youtube.com/watch?v=B281mrPUGjg
seek to about 31mins for the scroll view information.
This may help in the setup of UIScrollView programatically:
https://sheikhamais.medium.com/how-to-use-the-new-uiscrollview-programmatically-baf270ee9b4

How can I fill image in scroll view to fill screen?

I am playing around with scroll views, and I've run into an issue I'be stuck with. I have a view controller create in Storyboard. The view controller contains a scroll view which fills the entire superview.
I then added the images programmatically to the scroll view. The images do show within the scroll view and paging works just fine. Only problem is the scroll view is set ti fill superview but the image view that hold the images seems like it stops above where the navigation bar would be. How can I have the image view fill the whole view within the scroll view?
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pagingView: UIPageControl!
var images = [UIImage]()
var frame = CGRect(x: 0, y: 0,width: 0,height: 0)
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
scrollView.isPagingEnabled = true
images = [UIImage(named: "Slide1")!, UIImage(named: "Slide2")!, UIImage(named: "Slide3")!, UIImage(named: "Slide4")!]
pagingView.numberOfPages = images.count
// This is where I think I'm having the height problem.
for i in 0..<images.count {
let imageView = UIImageView()
let x = self.view.frame.size.width * CGFloat(i)
imageView.frame = CGRect(x: x, y: 0, width: self.view.frame.width, height: self.view.frame.height)
imageView.contentMode = .scaleAspectFill
imageView.image = images[i]
scrollView.contentSize.width = scrollView.frame.size.width * CGFloat(i + 1)
scrollView.addSubview(imageView)
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
pagingView.currentPage = Int(pageNumber)
}
After setting nav bar to hidden, here is the output
Scroll view background color is red
In this case you need to enable the parent view clipsToBounds. Set UIScrollview clipsToBounds property to True.
Programmatically scrollView.clipsToBounds = true
In UIStoryBoard - Click the view->Attributes Inspector
If you would like to see the whole screen, make sure to add the topConstraint of scrollView assigned superView and hide the navigationBar in viewWillAppear,
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: animated)
}
Make sure to remove the status bar by
override var prefersStatusBarHidden: Bool {
return true
}
Update the Y position of Image.
imageView.frame = CGRect(x: x, y: **self.scrollView.frame.minY**, width: self.view.frame.width, height: self.view.frame.height)
Update the scrollView topConstraint by -20.

UIScrollView does not scroll in customView

I'm making a custom view and it contains a UIScrollView. But this scroll view does not scroll.
The view hierarchy is as follows:
- mainView
- UIScrollView
- contentView
A picture for illustration purposes
Here is my custom view code:
class MyCustomView: UIView {
#IBOutlet var mainView: UIView!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var scrollViewContetnView: UIView!
// MARK: - Methods
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.customInit()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.customInit()
}
// MARK: Custom
func customInit() {
Bundle.main.loadNibNamed("EmoKeyboard", owner: self, options: nil)
self.addSubview(mainView)
self.mainView.frame = self.bounds
self.mainView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
func makeTabItem(count: Int) {
for i in 0...count {
let icon = UIButton()
icon.frame.size = CGSize(width: 28, height: 28)
icon.center.y = self.scrollViewContentView.center.y
icon.frame.origin.x = 10 + (CGFloat(i) * 28) + (CGFloat(i) * 10)
icon.backgroundColor = UIColor.black
self.scrollViewContentView.addSubview(icon)
}
}
}
What am I doing wrong?
You have to manually set contentSize of your scrollView based on buttons count or for every button add constraints.
Another possible(!) easier way is adding UIStackView as subview of your scrollView and add each button with height/width constraints to it.
Add contentSize:
scrollView.contentSize = CGSize(width: 0, height: 900) //You can use self view size height to set height means replace 900 according to your requirment
Every time you add a UIButton to your scrollViewContentView, you should update the width of the scrollViewContentView, because its width should be equal to the width of all the UIButton items that you are adding to it plus the sum of spacing between the items.
calculate the content rect in
ViewController ~> viewDidLayoutSubviews
var contentRect = CGRect.zero
for view in contentView.subviews {
contentRect = contentRect.union(view.frame)
}
contentRect = contentRect.union(padding)
apply the rect
scrollView.contentSize = contentRect.size

How to set UIScrollView contensize when content is load asynchronously

My view hierarchy is this
PhotoDetailViewController.swift
View
UIScrollView
UIImageView
I set this up using storyboard, and add four constraints(top=0, bottom=0, leading=0, tailing=0) to UIScrollView, four constraints(top=0, bottom=0, leading=0, tailing=0) to UIImageView, but there are two error says
"ScrollView has ambiguous scrollable content width"
"ScrollView has ambiguous scrollable content height"
I understand that this is because I haven't set UIScrollView contentSize, but What I trying to do is load photo from PHAsset asynchronously, so I can only get the photo size at run time. So the question is:
1:Given that photo size can only be get at run time, how to solve the "ambiguous scrollable content" error?
2:In which View's life cycle method should I call PHImageManager.requestImageForAsset? because I think I should set UIScrollView contentSize programmatically, but when?
update with PhotoDetailViewController.swift
import UIKit
import Photos
class PhotoDetailViewController : UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var imageViewBottomConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewLeadingConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewTrailingConstraint: NSLayoutConstraint!
var devicePhotosAsset : PHFetchResult!
var index = 0
var photo : UIImage!
var imgManager:PHImageManager!
#IBOutlet weak var imageView : UIImageView!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func awakeFromNib() {
self.imgManager = PHImageManager()
}
override func viewDidLoad() {
super.viewDidLoad()
self.displayPhoto()
}
override func viewWillLayoutSubviews() {
super.viewDidLayoutSubviews()
updateMinZoomScaleForSize()
updateConstraintsForSize()
}
func displayPhoto () {
_ = self.imgManager.requestImageForAsset(self.devicePhotosAsset[self.index] as! PHAsset, targetSize: PHImageManagerMaximumSize, contentMode: .AspectFit, options: nil, resultHandler: {(result, info) -> Void in
NSOperationQueue.mainQueue().addOperationWithBlock(){
self.imageView.image = result
}
})
}
private func targetSize() -> CGSize {
let scale = UIScreen.mainScreen().scale
let targetSize = CGSizeMake(CGRectGetWidth(self.imageView.bounds)*scale, CGRectGetHeight(self.imageView.bounds)*scale)
return targetSize
}
private func updateMinZoomScaleForSize() {
let size = scrollView.bounds.size
let widthScale = size.width / imageView.bounds.width
let heightScale = size.height / imageView.bounds.height
let minScale = min(widthScale, heightScale)
scrollView.minimumZoomScale = minScale
scrollView.zoomScale = minScale
}
func recenterImage(){
let scrollViewSize = scrollView.bounds.size
let imageSize = imageView.frame.size
let horizontalSpace = imageSize.width < scrollViewSize.width ? (scrollViewSize.width - imageSize.width)/2 : 0
let verticalSpace = imageSize.height < scrollViewSize.height ? (scrollViewSize.height - imageSize.height)/2 : 0
scrollView.contentInset = UIEdgeInsets(top: verticalSpace, left: horizontalSpace, bottom: verticalSpace, right: horizontalSpace)
}
private func updateConstraintsForSize() {
let size = scrollView.bounds.size
let yOffset = max(0, (size.height - imageView.frame.height) / 2)
imageViewTopConstraint.constant = yOffset
imageViewBottomConstraint.constant = yOffset
let xOffset = max(0, (size.width - imageView.frame.width) / 2)
imageViewLeadingConstraint.constant = xOffset
imageViewTrailingConstraint.constant = xOffset
view.layoutIfNeeded()
}
}
extension PhotoDetailViewController: UIScrollViewDelegate {
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(scrollView: UIScrollView) {
updateConstraintsForSize()
}
}
Your existing constraints are enough to set the content size, it's just that it's based on the image view intrinsic content size and that doesn't really exist until the image view has an image.
You can add a width and height constraint to the image view with default values and deactivate those constraints when the image is set to the view. Or you could use a placeholder image and avoid those extra constraints because you'd always have an intrinsic content size for the image view.
You should set two more constraint to your imageView.
Horizontally in Container (or you can say it center X)
Fixed Height
Second thing you can put UIView on Scrollview with Constraints like,
Top,leading,trailing,bottom,Horizontally in container(center x),fixed height).
Then add your imageview to that view. And can change it's constraint after getting image to resize it's height and width.
You can connect outlet of any constraint and can change it's constant programmatically.
Xcode UI builder has special type of constraint for such cases (when you can setup constraint only in runtime). It's so called "placeholder constraint" which will be removed at build time but helps to remove constraints errors for developing.
So solution is
Add some sample constraints IB and mark them as placeholders
Add needed constraints in runtime
When you get the data, just add these lines
float sizeOfContent = 0;
UIView *lLast = [yourscrollview.subviews lastObject];
NSInteger wd = lLast.frame.origin.y;
NSInteger ht = lLast.frame.size.height;
sizeOfContent = wd+ht;
yourscrollview.contentSize = CGSizeMake(yourscrollview.frame.size.width, sizeOfContent);
Hope this helps

Swift UIScrollView - strange padding

I need to make the flowers image flipping. Images must be with the same height, but the width to set automatically. I want them to scroll right and left
Here is my code:
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
var images = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
for i in 1...3 {
images.append(UIImage(named: "bild-0\(i).jpg")!)
}
var i: CGFloat = 0
var origin: CGFloat = 0
let height: CGFloat = scrollView.bounds.height
for image in images {
let imageView = UIImageView(frame: CGRectZero)
imageView.frame.size.height = height
imageView.image = image
imageView.sizeToFit()
imageView.frame.origin.x = origin
println(imageView.frame.size.width)
println(imageView.frame.origin.x)
println(imageView.frame.size.height)
println("asd")
origin = origin + imageView.frame.size.width
i++
scrollView.addSubview(imageView)
}
scrollView.contentSize.width = origin
scrollView.bounces = false
scrollView.pagingEnabled = false
}
}
Storyboard:
Problem (Padding from top! - Red color - is a background for UIScrollView):
Images are 765x510 300x510 and so on
UIScrollView height is 170
This is caused by scrolling insets:
Click your ViewController on Storyboard and go to file inspector, and you should see this dialog:
Untick the Adjust Scroll View Insets.

Resources