How to set scrollview height programmatically - ios

How can I set the scrollview height programmatically in Xcode 9 with Swift 4? I've set a constraint for the scrollview height and added that as an outlet. But when I change the outlet constant value programmatically it doesn't change the height.
Example:
#IBOutlet weak var scrollview_height: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
self.scrollview_height.constant = 245
}

The height of the ScrollView should be given by it's content and not for you to change manually. At best if you want to do something like that, you have a view inside the scrollView and change the size of that view instead.
Step-by-step:
Add a ScrollView to your view. Set it's constraints (no height or width)
Add a View inside the ScrollView and set it's constraints. Additionally for a vertical scroll you might want to set it's width equal to the SuperView and ensure it has a height.
Create an IBOutlet for the height of the view
update the constant value of the constraint in code
If it does not update as expected, run a layoutIfNeeded on your superview after updates

You have to increase the content Size of your scrollView instead of increasing the frame of scrollView.
self.scrollview.contentSize = CGSize(width: screenWidth, height: yourDesiredHeight)
the scrollable contentSize of scrollView will change According to it.

Related

How to add Scroll View in Swift 5?

I wanna add scroll view in my project but in swift 5 I can't add it I tried many ways
#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!
1.Add scrollView(1) in storyboard, add needed constraint to top/bottom/trailing/leading.
2.Then uncheck "Content Layout Guides" in Size inspector section for your scrollView.
3.Then you need to put into your scrollView new UIView(2), its constraints are for top/bottom/trailing/leading to superView(1) and equal width to superView(1).
4.Then the height of your view(2) you can add as constraint or you can add the content, which will give the height to your view(2).
Example with the height setted
Example with the content, which give the height to your view(2)
It works 100% when I Disabling the content layout guides in properties
If you use interface builder first of all add your scroll view and set scroll view constraint (top, bottom, leading and trailing) as (0,0,0,0). View hierarchy must be like this view -> scroll view -> view(content view). Again add constraints for your content view. Content view must have equal width and equal height with parent view (Scroll View). Control drag from content view to scroll view in Document Outline
For more information you can look at this https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithScrollViews.html
You don't need to uncheck Content Layout Guides(it's there to help us). It's actually not that hard to set it up. Here's how to do it using Xcode 11+ and supporting iOS 11+
1 - Add ScrollView and set top, bottom, leading and trailing constraints to 0 in relation to its superview
2 - Add a Content View(any UIView), drag a connection to the Content Layout Guide and set leading,top,trailing and bottom constraints to 0(make sure to set it to 0)
3 - Drag from your Content View to the Frame Layout Guide and set it to Equal Width
4 - Add a height constraint constant to the Content View
You can skip constraints altogether.
Add the ScrollView to your storyboard.
Create an IBOutlet in your ViewController.
Set the scrollview's height: scrollView.contentSize = (CGSize(width: desiredWidth, height: desiredHeight)
The desired width can be either a number or the width of another view. You can take the main view's width for exemple, by creating an IBOutlet to it: scrollView.contentSize = (CGSize(width: mainView.frame.size.width, height: desiredHeight)
The desired height is whatever value you require for the content to be shown in full while scrolling.
I find this way much easier to understand and control.

UITableView dynamic content size height inside UIScrollView with AutoLayout

I have a UIScrollView, inside this UIScrollView I have a UIView and inside the UIView I have some UITextField's, some UILabel's and at the bottom there is a UITableView.
I want the UITableView to fit it's content height, the UIView to fit it's content height and the UIScrollView to fit it's content height.
The UITableView height might change as I add / remove cells from it during usage.
What is the best way to handle it using AutoLayout?
- UIViewController
-- UIView
--- UIScrollView
---- UIView
----- UILabel
----- UITextField
----- UITextView
----- UITableView (at the bottom of the superview)
or as in the xib:
The best way to implement this is to scrap the hierarchy that you have now and do the following...
- UIViewController (or UITableViewController)
--- UITableView
----- UIView (as the tableView.tableHeaderView)
------- UILabel
------- UITextField
------- UITextView
----- Rest of the cells for the table view.
The tableView.tableHeaderView is a single (not reusable, concrete) view that is placed at the top of the content of the table view and scrolls with the content of the table view. It doesn't stick to the top of the screen like a section header view does.
This will allow you to delete the scroll view and place everything inside the table view and still doesn't change the methods that you are using to populate the cells as that remains untouched.
#Jan Greve is correct. But if you still want to do it
Set Bottom Space to Container constraint between the Table View and its super view to 0
Increase/decrease the height constraint of the Table View with each insert/delete (You will have to do this programmatically)
Set the content offset of the scrollview to the new view height
The best part of AutoLayout is now you don't have to worry about UIScrollView content size.
If you set all constraints properly(without any warnings) AutoLayout manage content size for scrollView itself.
Set all subview's constraints but don't add height and width constraints.
And for contentSize add bottom constraint of inner view (subview of scrollview) to UIScrollView. This will increaser scrollView content size and height as per inner view expand or shrink.
For more details: I asked question for same, you can check it. You can find code in question itself.
You can set a fixed height to the tableView and link the constraint to an outlet. Then you'd need to override viewDidLayoutSubviews() in order to set the height dynamically based on the contentSize of the table:
#IBOutlet weak var dynamicTVHeight: NSLayoutConstraint!
internal override func viewDidLayoutSubviews() {
let height = min(self.view.bounds.size.height, self.tableView.contentSize.height)
self.dynamicTVHeight.constant = height
self.view.layoutIfNeeded()
}

Update constraints of other elements when UITableView height change

I have a UITableView of which I am defining height as 200 in autolayout. Based on that I am laying out other elements below it like UITextField etc. After that in run time I am fetching data from server and populating in UITableView due to which i am updating UITableView's height based on its content size. Following code I am using for it
self.myTableView.frame = CGRectMake(0 , 0, self.myTableView.frame.width, self.myTableView.contentSize.height)
But due to this, all the elements placed below UITableView still appear at same location which they were while laying out in Autolayout. Means change in height of UITableView makes no difference to them. Following image depicts this problem. What could be possible solution for this?
Here you can see, text fields are getting overlapped on tableview at run time. I am using Swift 2 in Xcode 7.2
If you have all required constraints to your table view and other view.
Don't change the frame of TableView to change height of it.
Instead create IBOutlet of height constraint of your tablview.
e.g. say IBOutlet name is constraintTableViewHeight,
then you can the the hight easily.
constraintTableViewHeight.constant = yourNewHeightValue
//update all constraint of your view and its inner view
self.view.layoutIfNeeded();
Refer Image to create IBOutlet for your height Constraint.
Take IBOutlet of NSLayoutConstraint for tableView Height and set its value not set tableview frame it's not working if you are already given constraints for tableview so change tableview hight constant
like if you take tblHeight for tableView height then set tblHeight.constant = self.myTableView.contentSize.height
You have to create an outlet connection for your table view height constraint:
#IBOutlet var heightConstraint: NSLayoutConstraint!
and when you want to change table view height, you can change the constraint value like this:
heightConstraint.constant = newHeightValue
self.view.layoutIfNeeded()

UIScrollView does not Scroll completely

I have a ViewController. In it I put ScrollView with the View(contentView). Later I drag from contentView to View and set Equal Height. Now it scrolls, but not fully.
As you see there are it has continue below the textView, but it
doesn't scrolls. How can I fix it?
UIScrollView is able to automatically calculate it's content height and width, but you need to help it with this.
To do so you need to:
Bound contentView (in your case) to all sides of superview (which is Scroll View).
Let contentView to calculate it's sizes. Here is a small mistake in your approach. You've set height of the contentView equal to View's height. So basically Scroll View's contentSize.height is the same as View's height. Which is not really what you want with dynamic content.
Usually you want to set width of the contentView equal to View's width and do not set contentView's height. Instead you want to bind subviews of contentView to their superview in such a way that their superview (contentView) will calculate it's height automatically.
In your case I would bind:
pizza.jpg to left-top-right of superview (height of pizza.jpg will be set from intrinsic image size);
SAMPLE TITLE label - left-right to superview; top to pizza.jpg image;
Text View - left-bottom-right to superview; top to SAMPLE TITLE label; set a fixed height.
In this case contentView will define needed height by itself. Scroll View will set it's contentSize accordingly.
And your screen will be able to scroll vertically (it should be) ;)
You need to set the contentsize of the scrollview. Use the below code to do that:
func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, self.contentView.frame.size.height);
}
To use Autolayout with UIScrollView is tricky.
In your code you have to update height constraint for your contentView by calculating height of subviews of contentView and that will automatically update the contentSize for your ScrollView and you can scroll through all subviews.
For more info to use Autolayout+UIScrollView your can read this.
According to this link (thanks to this Matt's answer first), UIScrollView acts differently with AutoLayout than the other views.
Subviews of a scrollView set their constraints from the contentView of the scrollView and not the scrollview directly. This allows the content to scroll.
So :
Add a UIView to your scrollView, this will represent the contentView of your scrollView. Add constraints to top, bottom, trailing, leading from the view to its superView
Interface Builder complains. Here you see the different between a basic view and a scrollView. The reason is a contentView has to be fill to know its size. So add a equal width from the contentView to the scrollView
The contentView knows now its width but not its height. So add your labels and your UIImage as subviews of the contentView. Add constraints from bottom to the top. Don't miss to add a height constraint to the UIImageView.
It should look like this :
Hope this helps
Read this (from Matt once again) for further informations

UIView within UIScrollView keeps setting its width and height to 0

My directory structure is this:
UIView
UIScrollView
UIView
Label
Label
I want to be able to center the uiView (the second one) to adjust its width for iphone 6. I set the uiscrollview width and height to constraint with 0 on all sides. Then when i set UIView constraints to all 0, which makes the uiview disappear. I don't know why it's disappearing?
If you are using autolayout with scrollView, you have some options.
First, you can set width and height constraint to contentView, so scrollView gets it as a contentSize. Second (in addition to first), you can fill the scrollView of views with size constraints. Third, you can set contentSize manually. Forth, you can make outlets for contentView size constraint and set them in viewWillLayoutSubviews manually.
So, your view dissappear because contentSize of scrollView is zero.

Resources