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.
Related
I am trying to replicate the visual effect that apple uses with several of its applications where the navigation bar and a toolbar are combined. Here is an example:
The peculiarity is that the two have and share a somewhat transparent background effect, say .configureWithDefaultBackground() (In the picture you can see how the navigation bar and the toolbar share the same background blur effect)
Trying to replicate the design, when the content of the collection has not yet started to scroll, the background color of the toolbar does not behave like the navigation bar and when it does start scrolling, the effect is shared. Here are some images
Trying to replicate the design, when the content of the collection has not yet started to scroll, the background color of the toolbar does not behave like the navigation bar and it has a "grey" background color while in the apple one, before you start to scroll, both are white (or .systemBackground)
When you start scrolling, the two share the same background effect and behave as expected.
Here's some code:
private func configureNavBar() {
let navigationBarAppearanceStandard = UINavigationBarAppearance()
navigationBarAppearanceStandard.configureWithDefaultBackground()
let navigationBarAppearanceScrollEdge = UINavigationBarAppearance()
navigationBarAppearanceScrollEdge.configureWithOpaqueBackground()
navigationController?.navigationBar.standardAppearance = navigationBarAppearanceStandard
navigationController?.navigationBar.scrollEdgeAppearance = navigationBarAppearanceScrollEdge
navigationController?.navigationBar.standardAppearance.shadowColor = .clear
navigationController?.navigationBar.scrollEdgeAppearance?.shadowColor = .clear
}
func configureToolbar() {
let toolbarAppearance = UIToolbarAppearance()
toolbarAppearance.configureWithTransparentBackground() // .default & .opaque behave the same, gray color before scrolling
toolbar.scrollEdgeAppearance = toolbarAppearance
toolbar.compactAppearance = toolbarAppearance
toolbar.delegate = self
toolbar.translatesAutoresizingMaskIntoConstraints = false
}
private func layoutUI() {
view.addSubview(collectionView)
view.addSubview(toolbar)
NSLayoutConstraint.activate([
toolbar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
toolbar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
toolbar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
toolbar.heightAnchor.constraint(equalToConstant: 50),
collectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
collectionView.contentInset.top = 50
collectionView.verticalScrollIndicatorInsets.top = 50
}
Tried self.toolbar.setBackgroundImage(UIImage(), forToolbarPosition: .top, barMetrics: .default), but makes it transparent and not blurry.
Does anyone know why the toolbar is grayed out and not the same color as the navigation bar before you start scrolling the collectionView?
I have a UICollectionView and I'm trying to design my UICollectionViewCell's using SwiftUI. I've seen two examples, one and two that have done this in the following manner in their UICollectionViewCell:
let controller = UIHostingController(rootView: SomeSwiftUIView)
let view = controller.view!
view.translatesAutoresizingMaskIntoConstraints = false
addSubview(view)
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
view.topAnchor.constraint(equalTo: contentView.topAnchor),
view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
This works fine visually, but a problem I'm having is I do not have user interaction with the SwiftUI view. For example, if I have a Button in the SwiftUI view, the action is not performed when you tap the button. If a List is in the SwiftUI view, you cannot scroll this view. (I'm not trying to put a List in it, this is just an example)
Any recommendations on where to go from here? Thanks!
I solved this by constraining the view to the cell rather than the contentView, and it is working fine now.
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: leadingAnchor),
view.topAnchor.constraint(equalTo: topAnchor),
view.trailingAnchor.constraint(equalTo: trailingAnchor),
view.bottomAnchor.constraint(equalTo: bottomAnchor)
])
As I suspected, this was a layering issue.
I'm using autolayout constraints to make an UILabel stay at the top of a modal.
title.topAnchor.constraint(equalTo: view.topAnchor, constant: 10)
title.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 5)
title.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -5)
title.centerXAnchor.constraint(equalTo: view.centerXAnchor)
The modal is presented at the center of the screen and its preferredContentSize is hardcoded as 312 width and 219 height.
However, on my iPhone 11, when my device is being rotated from portrait to landscape, the modal is whiteout firstly, and the UILabel flies into the view before rotation completes(img 1). But when my device is being rotated from landscape back to portrait, the UILabel rotates in place with the screen and never leaves the modal(img 2). Why there is such difference? What can I do to always make the UILabel rotates in place during the orientation change?
I feel like it might be related to my constraints but I couldn't figure out why. Could someone please help shed some light? Thanks!
Your constraints seem fine, you just have to activate those constraints.
NSLayoutConstraint.activate([
title.topAnchor.constraint(equalTo: view.topAnchor, constant: 10)
title.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 5)
title.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -5)
title.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
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.
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