I've pinned my UIPageControl at the bottom of the collection view controller using this function in viewDidLoad..
func setUpViewsAndConstraints(){
collectionView.addSubview(pageControl)
collectionView.bringSubviewToFront(pageControl)
pageControl.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
pageControl.bottomAnchor.constraint(equalTo: collectionView.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
}
but when I scroll through the cells (horizontally) the pageControl stays under the first cell and is left behind when I move on to the next cell...
I thought that just cells moved when scrolling and collectionView stay in place but it seems it's not the case, or I'm doing something wrong..
what am I missing here?
thank you in advance for the answers!
I advice you to keep the pageControl under the collectionView and not inside, as I can see you are adding a bottomAnchor at your pageControl to the same bottom of the collectionView; try to keep them separately and add a top constraint to your pageControl to the bottom of collectionView and add a centralAnchor to your ViewController
pageControl.centerXAnchor.constraint(equalTo: viewController.centerXAnchor).isActive = true
pageControl.topAnchor.constraint(equalTo: collectionView.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
And maybe a bottom constraint to your view
pageControl.bottomAnchor.constraint(equalTo: viewController.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
Obviously for this case you should have a UIViewController parent with a UICollectionView and a pageControl as children
Related
I'm trying to pin my UIImageView to the top via Autolayout and don't quite understand how to pin it to the Navigation Item itself.
It turns out to the view itself
How to write this line correctly?
imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 10) = true
The navigation bar is automatically added as a part of the safe area. You need to pin the top of your view to the safeAreaLayoutGuide like this:
imageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10) = true
Same goes for the tab bar.
I have 2 buttons on the screen, the lower one is anchored to the view's bottom anchor, and the one above that is anchored to the lower button's top anchor. However, this throws an error "'Unable to activate constraint with anchors and because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'
I have already added both buttons to the view (view.addSubView) and set translatesAutoresizingMaskIntoConstraints = false, no help.
view.addSubview(topButton)
topButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
topButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
topButton.widthAnchor.constraint(equalToConstant: 180).isActive = true
topButton.bottomAnchor.constraint(equalTo: lowerButton.topAnchor, constant: 120).isActive = true
view.addSubview(lowerButton)
lowerButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
lowerButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
lowerButton.widthAnchor.constraint(equalToConstant: 220).isActive = true
lowerButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
What I want for to happen is the lower button anchored to the view's bottom anchor, and the top button's bottom anchor anchored to the lower button's top anchor
You are adding constraints involving lowerButton before you actually add it to the view hierarchy. Simply move view.addSubview(lowerButton) to right below adding the topButton.
Using Xcode 10, iOS 11.4+, Swift 4
I have a series of UIViewControllers that I am navigating through,
each of which is being placed into a ContainerView.
Based on which VC is pushed, I am hiding/showing the Top or Bottom views (shown in gray) in the Main Controller while the ContainerView is always in the middle (light blue).
What I would like to do is set the constraints so that the ContainerView is appropriately sized when the Top or Bottom views are shown/hidden.
For example, when the "Main Menu" is shown, the ContainerView should fill the entire Main Container view (Top and Bottom views will be hidden)
When "Item1" is shown, the Top view will be shown and the Bottom view hidden. Therefore, ContainerView should fill the Main Container view left, right, and bottom, but the ContainerView Top should be constrained to the Top view bottom.
When "Item5" is shown, the Top and Bottom views will also be shown.
Therefore, ContainerView should fill Main Container view left, right, and be constrained to the Top view bottom, and the Bottom view top (as shown in the Main Container)
I've tried using code like this to fill the entire Main view:
NSLayoutConstraint.activate([
ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0),
ContainerView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0),
ContainerView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0),
ContainerView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0)
])
However, the ContainerView never changes, and Xcode gives me a lot of warnings like:
[LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one
you don't want.
Here's another screenshot from the Storyboard:
Here's a link to download my sample project:
https://gitlab.com/whoit/containerviews
How can I correctly modify the constraints to accomplish this?
As I've mentioned in the comment, you should have used UIStackView for your top / bottom views visibility controlling.
You will need a UIStackView with following attributes:
Axis: Vertical
Alignment: Fill
Distribution: Fill
Spacing: As per your need
The stack view will contain the Top View, Container View and Bottom View respectively as its sub views.
You need to pin all the sides (leading, trailing, top & bottom) of this stack view to its superview (view controller's view). And as you need some height constraints for your top & bottom view, you give them as your need.
So basically your stack view is now capable of resizing its sub views when you hide any of them. You just need to perform:
theSubViewNeedsTobeHidden.isHidden = true
I've made a working demo for you that can be found here.
Issues
1) You're adding new constraints all the time, as this lines create a new constraints, each time they're getting called:
ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0)
2) In the beginning, the MainContainerView is not constraint at all
Solution
I would suggest following:
add those four constraints in the storyboard instead
create IBOutlets for the height-constraints of your top and bottom views.
set the constants of those to 0 (when hiding them)
(optional) for sure you can still fade them in/out by setting their alpha as well, and then add the height constant to the completion block.
Note:
Hidden views (alpha = 0 or isHidden = true) are still taken into account for layouting. That means, your constraints are still valid, when the views are hidden. But to make them look like hidden for the layouting as well, you'll then have to set theirs height constants to 0.
Code
#objc func hideControlViews(_ notification: Notification){
let userInfo = notification.userInfo! as! [String : Bool]
//print("Got top view notification: \(String(describing: userInfo["hide"]))")
if (userInfo["hidetop"]!) {
self.topViewHeightConstraint.constant = 0
} else {
self.topViewHeightConstraint.constant = 64
}
if (userInfo["hidebottom"]!) {
self.bottomViewHeightConstraint.constant = 0
} else {
self.bottomViewHeightConstraint.constant = 108
}
self.view.layoutIfNeeded()
}
I know how to add a ViewController to a container if using an outlet through interface builder. You just drag an outlet from container to ViewController and boom, everythings all set and done. But when it comes to doing it programatically, I can't find any answer on the net? Can anyone give me a sample code? Thanks in advance.
Let's say I have 2 View Controllers and 1 containerView. First Controller is the parent and inside is the container view and inside the containerView is the secondView Controller.
You need to first add constraints with parent view and container view, then you also need to add constraints to your container controller. Finally you should add the didMoveToParent in the end of setting all the constraints.
The example is as follows, you can do a similar thing in your case.
NSLayoutConstraint.activateConstraints([
containerView.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant: 10),
containerView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor, constant: -10),
containerView.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 10),
containerView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor, constant: -10),
])
NSLayoutConstraint.activateConstraints([
controller.view.leadingAnchor.constraintEqualToAnchor(containerView.leadingAnchor),
controller.view.trailingAnchor.constraintEqualToAnchor(containerView.trailingAnchor),
controller.view.topAnchor.constraintEqualToAnchor(containerView.topAnchor),
controller.view.bottomAnchor.constraintEqualToAnchor(containerView.bottomAnchor)
])
controller.didMoveToParentViewController(self)
or you can also refer this: https://codedump.io/share/jVuaGlB85VtK/1/how-to-add-a-container-view-programmatically
To start with, here's a mockup of the layout I'm trying to accomplish in Swift.
And here's what I have so far,
So here's the problem. Notice that in the second image the green UIView overflows exceeding the TableViewCell height.
In my Main TableViewController class I've defined each cell to be 120 pixels in height, and the green UIView 10 pixels short of the cell height with the 10 pixels on top as a separator between subsequent cells.
Cell height definition:
var itemHeight = [CGFloat](count: 2, repeatedValue: 120.0)
UIView constraints:
foregroundView.topAnchor.constraintEqualToAnchor(foregroundView.superview?.topAnchor, constant: 10).active = true
foregroundView.leftAnchor.constraintEqualToAnchor(foregroundView.superview?.leftAnchor, constant: 20).active = true
foregroundView.widthAnchor.constraintEqualToAnchor(foregroundView.superview?.widthAnchor, constant: -40).active = true
foregroundView.heightAnchor.constraintEqualToConstant(110).active = true
Any ideas on what might be causing the UIView overflow?
Thanks in advance!
Please let me know if you'd like to see the code in context :)
Remove two lines of code from your project:
foregroundView.layoutIfNeeded()
And
containerView.layoutIfNeeded()
They are forcing an untimely laying out of content that is causing your problem.