SwiftUI View in UICollectionViewCell - swift

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.

Related

UINavigationBar & UIToolBar do not share the same appearance effect

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?

Swift tvOS - TabBar Trailing Accessory View Focus

The tabbar has a trailingAccessoryView that the documentation indicates can be used for some user actions. However, while I can put a view inside this accessory view, it does not get the focus at any point. Is there a means to allow this view to get the focus when swiping right from the tabbar?
let symbolConfig = UIImage.SymbolConfiguration(pointSize: 30, weight: .bold, scale: .large)
let guideButton = UIButton()
guideButton.setImage(UIImage(systemName: "list.bullet", withConfiguration: symbolConfig), for: .normal)
guideButton.addTarget(self, action: #selector(test), for: .primaryActionTriggered)
guideButton.translatesAutoresizingMaskIntoConstraints = false
tabBar.trailingAccessoryView.addSubview(guideButton)
guideButton.topAnchor.constraint(equalTo: tabBar.trailingAccessoryView.topAnchor).isActive = true
guideButton.trailingAnchor.constraint(equalTo: tabBar.trailingAccessoryView.trailingAnchor, constant: 0).isActive = true
As a note, I have tried setting: tabBar.trailingAccessoryView.isUserInteractionEnabled = true to no effect.
While not an exact answer, I wound up getting around this issue by adding the button to the tabbar's view rather than to the trailingAccessoryView. Not clear why the accessory view wouldn't work, but this does turn out to be a workable answer that does the job just as well.

Why does NSScrollView display a white track?

I am programming with macos, in swift. I have a few paragraphs of text (Lopem Ipsum - to test) inside a scroll view. Also a title, which is a NSTextView, positioned above.
When I present it in a popover, all looks fine.
However in another part of the project, I present a the same contents (using a copy of the same layout code - below), but this time in a modal window.
It has a ugly white track! That must be connected to the scroll view, since it only appears when I set the vertical scrollbar - hasVerticalScroller, which is necessary because I want vertical scrolling. As it should, the knob highlights on mouse-hover and it scolls properly.
It probably would be fine with a solid white background. But that's not what I want! Thus I have the setting scrollView.drawsBackground = false.
I've tried: scrollView.verticalScroller?.highlight(false); scrollView.verticalScroller?.wantsLayer = true; scrollView.verticalScroller?.layer?.backgroundColor = NSColor.clear.cgColor - no luck!
Even tried with only one paragraph (ie. no scroll), still the same.
I am using code similar to this:
class ViewController: NSViewController {
let scrollView = NSScrollView()
let textView = NSTextView()
override func viewDidLoad() {
super.viewDidLoad()
textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
textView.autoresizingMask = .width
textView.isVerticallyResizable = true
textView.textContainer?.widthTracksTextView = true
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.documentView = textView
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}
}
What can I do to have a clear (no background) track on the scrollbar?
scrollView.scrollerStyle = .overlay

Autolayout with Navigation Item

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.

How to keep pageControl in place while scrolling in a UICollectionView?

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