UIScrollView Subviews not expanding to fill width (Autolayout) - ios

I'm using the following code to constrain a view to the left and right anchors of a parent UIScrollView.
Despite the right anchor and the left anchor being set to the ScrollView's left and right anchors, the view does not expand to fill the scrollview.
Note: The gray background in this image is the UIScrollView's background, so I know that's properly constrained to its parent view.
Code:
self.wtfView.translatesAutoresizingMaskIntoConstraints = false
self.wtfView.backgroundColor = UIColor.orange
self.wtfView.topAnchor.constraint(equalTo: self.passwordField.bottomAnchor, constant: 40.0).isActive = true
self.wtfView.leftAnchor.constraint(equalTo: self.containerView.leftAnchor, constant: 40.0).isActive = true
self.wtfView.rightAnchor.constraint(equalTo: self.containerView.rightAnchor, constant: 40.0).isActive = true
self.wtfView.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
self.wtfView.bottomAnchor.constraint(equalTo: self.containerView.bottomAnchor, constant: 40.0).isActive = true
https://imgur.com/a/U88iW
Edit:
The following code works correctly, but I would prefer to use the left+right anchor technique to specify the width, and not at a width constraint. Shouldn't that be possible?
self.wtfView.translatesAutoresizingMaskIntoConstraints = false
self.wtfView.backgroundColor = UIColor.orange
self.wtfView.topAnchor.constraint(equalTo: self.passwordField.bottomAnchor, constant: 40.0).isActive = true
self.wtfView.leftAnchor.constraint(equalTo: self.containerView.leftAnchor, constant: 40.0).isActive = true
self.wtfView.widthAnchor.constraint(equalTo: self.containerView.widthAnchor, constant: -80.0).isActive = true //THE DIFFERENT ONE
self.wtfView.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
self.wtfView.bottomAnchor.constraint(equalTo: self.containerView.bottomAnchor, constant: 040.0).isActive = true

The reason for this is that the contentView of the UIScrollView still doesn't know that you want it to take up the width of it's parentView.
You can fix this by adding the following constraint in iOS11:
self.containerView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
This says "Hey, I want you to lock the content Width to the width of the superview.
Pre iOS 11 you can simply constrain a subview to both the parent view's left and right anchors AND the content view's left and right anchors.
Like so:
self.wtfView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 40.0).isActive = true
self.wtfView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 40.0).isActive = true
Much like, Aleksei's recommendation you are now constraining the width to a rigid value ( the width of the parent view ), and the scrollview will use that to decide the width of the scrollview.

may be try to provide:
self.wtfView.widthAnchor.constraint(equalTo: self.containerView.widthAnchor, constant: -40.0).isActive = true

Related

Search bar looks weird if width is less than 116

I am trying to create square search bar but when I set width less than 116, search icon and textfield area moved out of search bar. Please refer first search bar of screenshot.
I have fixed this issue by adding following code to set constraints manually for searchTextField.
searchBar.searchTextField.translatesAutoresizingMaskIntoConstraints = false
searchBar.searchTextField.leftAnchor.constraint(equalTo: searchBar.leftAnchor, constant: 8).isActive = true
searchBar.searchTextField.rightAnchor.constraint(equalTo: searchBar.rightAnchor, constant: -8).isActive = true
searchBar.searchTextField.topAnchor.constraint(equalTo: searchBar.topAnchor, constant: 6).isActive = true
searchBar.searchTextField.bottomAnchor.constraint(equalTo: searchBar.bottomAnchor, constant: -6).isActive = true
While expanding width, I marked translatesAutoresizingMaskIntoConstraints as true.
searchBar.searchTextField.translatesAutoresizingMaskIntoConstraints = true

UIView in UIScrollView respects some constraints but not other

I need to add a containerView inside a UIScrollView, and then add multiple subviews in the containerView. For some reason, the containerView does not respect the top/bottom/left/rightAnchor constraints, but it works with width/height/centerX/centerYAnchor
NOTE: If the superview is a UIView instead of a UIScrollView, it works fine.
The project is 100% code based. Using Swift 4.1 and Xcode 9.4
This does not work
containerView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true
containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0).isActive = true
containerView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
containerView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true
This works
containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
containerView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
containerView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor).isActive = true
In both cases the scrollView.constraints array includes 4 constraints total.
The interesting thing is that the printout of them is different. Some of the constraints that don't work (.top and .left) are printed using the Autolayout Visual Format Language. Also, note the (LTR) in the third one:
ScrollView [
<NSLayoutConstraint:V:|-(0)-[UIView] (active, names: '|':UIScrollView:)>,
<NSLayoutConstraint:UIView.bottom == UIScrollView.bottom (active)>,
<NSLayoutConstraint:H:|-(0)-[UIView](LTR) (active, names: '|':UIScrollView:)>,
<NSLayoutConstraint:UIView.right == UIScrollView.right (active)>]
The constraints that work are printed as follows:
ScrollView [
<NSLayoutConstraint:UIView.width == UIScrollView.width (active)>,
<NSLayoutConstraint:UIView.height == UIScrollView.height (active)>,
<NSLayoutConstraint:UIView.centerX == UIScrollView.centerX (active)>,
<NSLayoutConstraint:UIView.centerY == UIScrollView.centerY (active)>]
I researched StackOverflow and found a couple of questions like this, but they didn't really help me explain what the problem is (or the UIScrollView requirements for constraints).
Any ideas?
UIScrollView needs some contents in it to be scrolled. The view you are adding (inside scrollview), does not have size (height and width), so scroll view can't identify size of its content.
Add size for a view (inside scrollview) and it will work.
containerView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true
containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0).isActive = true
containerView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
containerView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true
// Size constraints
containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
// To check scrolling of container view; try this
containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor + 50.0).isActive = true
containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor + 50.0).isActive = true
It's because the UIScrollView requires it's contentSize to be set in some way. By anchoring the UIView's layout to the sides of the UIScrollView, auto layout still doesn't have an explicit idea of what contentSize of the UIScrollView.
Since the UIScrollView is probably anchored to some parent view, the height and width of the UIScrollView is already defined. By giving a UIView these constraints, auto layout can determine the size of the UIView and then use that size to set the contentSize of the UIScrollView.
Go through the following points in order to use scrollview in your application.
1. First add UIScrollview and give it constrain in view(left, right,width,height).[![enter image description here][1]][1]
2. Now each scrollview has content view which should be there , we cannot add our required views directly to UIScrollview.
3. Add view to scrollview(we name it content view) , give it top,bottom, left and right constrain. Apart from these we need to add height and width constrain to the content view.
4. If you want to have vertical scrollview then give width equal to scrollview and a proper height (like height constrain = 600)or greater than scrollview height.
5. If you want to have horizontal scrollview then give height equal to scrollview and width greater than actual width of scrollview.
Have a look at the constrain of content view added below

iOS digital number from different table view cell is not aligned as expected

I have a label called dollarLabel in custom table view cell, and set its auto layout constraints and appearance as following code snippets:
// Dollar label constraint.
dollarLabel.translatesAutoresizingMaskIntoConstraints = false
dollarLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8).isActive = true
dollarLabel.leadingAnchor.constraint(equalTo: subCategoryLabel.trailingAnchor, constant: 8).isActive = true
dollarLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8).isActive = true
dollarLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8).isActive = true
dollarLabel.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.3).isActive = true
// Dollar label appearance.
dollarLabel.textAlignment = NSTextAlignment.right
dollarLabel.font = UIFont.boldSystemFont(ofSize: 30)
dollarLabel.adjustsFontSizeToFitWidth = true
And the cells are shown as below:
I’m wondering why the dollar symbol of the third row is not aligned as the first and the second dollar symbol?
I set its textAlignment property to NSTextAlignment.right, and I expect that the three dollar symbol should be aligned vertically when the digital number have the same length.
What’s going wrong about my code?
Many thanks!

ios correct way to use constraintLessThanOrEqualToSystemSpacingAfter for trailingAnchor

I'd like to programmatically layout a UILabel that should fit the width of the screen, with the system spacing as left and right insets. Here's my code:
statusLabel.font = UIFont.systemFont(ofSize: UIFont.smallSystemFontSize)
statusLabel.numberOfLines = 0
statusLabel.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(statusLabel)
statusLabel.topAnchor.constraint(equalTo: otherView.bottomAnchor, constant: 0),
statusLabel.leadingAnchor.constraintEqualToSystemSpacingAfter(view.safeAreaLayoutGuide.leadingAnchor, multiplier: 1),
statusLabel.trailingAnchor.constraintLessThanOrEqualToSystemSpacingAfter(view.safeAreaLayoutGuide.trailingAnchor, multiplier: 1),
statusLabel.bottomAnchor.constraint(equalTo: someOtherView.topAnchor, constant: 0)
Here is the result:
the label is laid out using the system spacing as the left inset, as intended, but its trailingAnchor seems to be equal to the superview's trailingAnchor rather than adding a system spacing between the two.
I've tried using constraintEqualToSystemSpacingAfter and constraintGreaterThanOrEqualToSystemSpacingAfter but got the same results.
Any ideas on how to get the system spacing between the label and its superview's trailing anchors?
Reverse the order Like this
view.safeAreaLayoutGuide.trailingAnchor.constraintEqualToSystemSpacingAfter(statusLabel.trailingAnchor, multiplier: 1).isActive = true
view first & statusLabel next.

Applying Constraints Programmatically to UITableViewCell and SubViews

I am trying to learn how to apply constraints to build a UITableViewCell. I am using iOS 10 using Swift. Here is my requirement.
I want to apply constraints to the green control which is a button and make sure that it is on the right hand side as shown above.
countView.widthAnchor.constraint(equalToConstant: 100).isActive = true
countView.heightAnchor.constraint(equalToConstant: 44).isActive = true
I have supplied the width and height constraints as above. But I don't know how to put it on the right hand side of the cell with some space as a margin.
UPDATE: I don't see anything on the screen.
countView.backgroundColor = UIColor.green
self.addSubview(countView)
countView.widthAnchor.constraint(equalToConstant: 100).isActive = true
countView.heightAnchor.constraint(equalToConstant: 44).isActive = true
countView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 20).isActive = true
countView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true

Resources