NavigationBar prefersLargeTitle not working - swift

Using iOS 13.3,
I observe a strange behaviour of the navigationBar. If dragging up, the navigationBar contracts. (see video)
Don't worry about the tabs that are part of the navigationBar. The strange behaviour also happens without them. And also the fact that the ViewController presents in a modal sheet is irrelevant - the strange contraction behaviour also happens in a classic view. So far, I only knew this contracting behaviour from a SearchBar. But no such is present here.
How can I always keep the navigationBar at a fixed large size ?
I tried without success....
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always

I finally found the solution:
Since there was a tableView in the screen, the following was needed to prevent the contracting of the navigationBar:
tableView.isScrollEnabled = false
If your navigationBar has a custom height or for other reasons, you can also set the tableView's Insets to place it downwards like this:
tableView.contentInset = UIEdgeInsets(top: 90.0, left: 0.0, bottom: 0.0, right: 0.0)

Related

UIStackView - arranged views are overlapping

I've been struggling for the past hours to add custom views to a UIStackView. The StackView is placed inside a UIScrollView, with constraints set to each margin of the ScrollView. Everything is design in a Storyboard.
Then in code I have the following for loop which should add my custom views to the stack:
for name in names {
let initialChildProfile = ChildProfileView.loadFromNibNamed(nibNamed: "ChildProfileView") as! ChildProfileView
initialChildProfile.frame = CGRect(x: 0, y: 0, width: childrenStackOutlet.frame.size.width, height: initialChildProfile.frame.size.height)
initialChildProfile.isUserInteractionEnabled = true
childrenStackOutlet.addArrangedSubview(initialChildProfile)
}
I've done this so many times before and everything went fine, but this time the custom views are overlapping each other. Only if I set the spacing to something larger than 0, I can actually see that is more than 1 view.
I tried setting the "translateAutoresizingMaskIntoConstraints" to false, I tried setting hardcoded values for the frame of the custom views, different constraints to the stack, even removed it from the scrollview. But nothing works.
PS I tried the few solutions I've seen online. Still nothing.
Thank you.
the problem is autolayout
for name in names {
let initialChildProfile = ChildProfileView.loadFromNibNamed(nibNamed: "ChildProfileView") as! ChildProfileView
initialChildProfile.translatesAutoresizingMaskIntoConstraints = false
initialChildProfile.widthAnchor.constraint(equalToConstant: childrenStackOutlet.frame.size.width).isActive = true
//initialChildProfile.heightAnchor.constraint(equalToConstant: self.view.frame.width - 50).isActive = true
initialChildProfile.isUserInteractionEnabled = true
childrenStackOutlet.addArrangedSubview(initialChildProfile)
}

Half screen and full screen bottom sheet with material components for iOS (swift)

I'm using material components for iOS for making a draggable bottom sheet, that starts half screen (preview mode), and you can drag to full screen. But I don't know how, and the documentation is not very complete. https://material.io/develop/ios/components/bottom-sheet/
I present my DetailViewController within the MDCBottomSheetController:
let graphDetailViewController = UIStoryboard.detail().instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
let bottomSheet: MDCBottomSheetController = MDCBottomSheetController(contentViewController: graphDetailViewController)
bottomSheet.preferredContentSize = CGSize(width: self.view.frame.size.width, height: self.view.frame.size.height / 2)
present(bottomSheet, animated: true, completion: nil)
With this code, my vc is appearing half screen, but it's not possible to drag it up to full screen.
Is anyone experiences with material components (bottom sheet) for iOS and could help me?
Thanks a lot!
Everything is right except you set the preferredContentSize to be 1/2 the screen height.
bottomSheet.preferredContentSize = CGSize(width: self.view.frame.size.width, height: self.view.frame.size.height / 2)
Is the line causing your error. That line is telling the bottom sheet that there is no more content to scroll. You can delete it. If you want to have your contentViewController be a scroll view you may want to use the trackingScrollView property.

Header View behind NavigationBar [duplicate]

I have a UICollectionView that is the entire view but it lives inside "view" (it is not UICollectionViewController). Adding a cell to this collection view shows it in the following order in storyboard:
This is how it looks in the emulator:
I don't understand how to get rid of that view. All the insets are at zero in Storyboard Size Inspector for collection view. Just to be sure, I also have the following code:
override func viewWillLayoutSubviews() {
let layout = self.collectionViewProducts.collectionViewLayout as! UICollectionViewFlowLayout
let containerWidth = UIScreen.main.bounds.size.width - 40.0
let itemWidth = (containerWidth / 3.0)
let itemHeight = (itemWidth / 0.75) + 30
layout.sectionInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
}
How can I get rid of that top padding?
You can fix top padding issue by considering one of the following method.
Method 1: Natural way to fix your problem by setting up your collectionView dimensions properly from StoryBoard.
Method 2: **Updated**
You can validate collection frame in viewDidLayoutSubviews or viewWillLayoutSubviews
override func viewDidLayoutSubviews() {
collectionView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
}
Method 3: You can Adjust Scroll View Insets from your StoryBoard Attributes Inspector.
Method 4: You can fix this issue programatically by adjusting CollectionView contentInset.
collectionView.contentInset = UIEdgeInsets(top: **Any Value**, left: 0, bottom: 0, right: 0)
Output with top padding 5:
Output with top padding 44:
Output with top padding 64:
I think because this viewController is embedded in a navigationController. Let select this viewController in the storyboard and uncheck Adjust Scroll View Insets:
There is one more way to resolve this issue and that is selecting collectionView -> scrollView Content Insets -> "Automatic" to "Never".
By default scrollView Content Insets value is Automatic. Please check the below image.
For more details check: UIScrollView.ContentInsetAdjustmentBehavior
https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior
Make your Navigation Controller > NavigationBar translucent by unchecking the Translucent check box in IB > Attribute Inspector, and it will work.
I also had the same problem, and i fixed it with a way totally ridiculous solution.
My collectionView contained several sections which had no title & no item cells.
The top, bottom inset values of the section insets were 10 respectively.
so each empty section charged height of 20 pixels.
I had 4 empty sections, and therefore, 80 top margins in the collection view.
Hope you check this as well if none of the above solutions works.

Translucent Status Bar with No Navigation Bar

Goal: To have a table view scroll so that it shows semitransparent under the status bar while not displaying a navigation bar.
Right now, I have my tableView set to the top anchor (so technically underneath the status bar). This sets the status bar to a solid looking color as you scroll up on the table view. I've set the navigationAppearance's barTintColor and translucent to YES with no luck.
Any ideas? The view is instantiated in a storyboard
Your question is hard to guess without any code.I believe you trying to achieve a translucent status bar when tableview content scroll like you mentioned in Apple Music app.
Try below code inside your viewdidLoad method.
Step 1: To hide navigation bar. If your controller embedded with navigationController.
navigationController?.navigationBar.isHidden = true
Step 2: Place a statusBar size UIView to your controller to act as a translucent status Bar with adjusting alpha value.
let statusBarView = UIView(frame: CGRect(x:0, y:0, width:view.frame.size.width, height: UIApplication.shared.statusBarFrame.height))
statusBarView.backgroundColor=UIColor.white
statusBarView.alpha = 0.8 // set any value between 0 to 1
view.addSubview(statusBarView)
Above code will produce the following output.Let me know the code works for you.
For more information how to set tableView frame and contentView take a look at my answer in the following link.
Update:
Improved Answer:
You can use UIBlurEffectView to achieve better translucent effect.
let statusBarView = UIView(frame: CGRect(x:0, y:0, width:view.frame.size.width, height: UIApplication.shared.statusBarFrame.height))
let blurEffect = UIBlurEffect(style: .extraLight) // Set any style you want(.light or .dark) to achieve different effect.
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = statusBarView.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
statusBarView.addSubview(blurEffectView)
view.addSubview(statusBarView)
Output:
As you described, your UITableView is right underneath the status bar. When you scroll down, the tableView's frame remains the same size and origin and won't go underneath the status bar. What you want to do is to set the constraint for your tableView to the top of the superview (not the Top Layout Guide) which means it would sit right under the status bar.
Because the status bar now hides the top 20px of your tableView you want to make a content offset:
tableView.contentInset = UIEdgeInsetsMake(top: 20, left: 0, bottom: 0, right: 0)
To make the scroll indicator start right under the status bar you also want to set an offset for it:
tableView.scrollIndicatorInsets = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)

Swift 3: UISearchBar in Popover ViewController shows up wider than expected (on iPad)

I have a view controller opened from a Popover segue - on iPhone displays this opens as a full page view controller (basically modally). On iPad it opens as a popover.
When opening the view on iPad the seachbar renders wider than the view of the popover. This does not occur on any of the iPhone screen sizes - Only iPad (as a Popover).
If I bring the UISearchBar to focus (tap on the textfield) the issue resolves itself until the view is opened again:
The UISearchBar is added programatically to a UIView of the desired dimensions.
Here is the code for initializing the SearchController
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.definesPresentationContext = false;
searchBarView.addSubview(controller.searchBar)
return controller
})()
I have tried removing .sizeToFit() and instead sizing based on a CGSize
controller.searchBar.sizeThatFits(CGSize(width: 375, height: 44)
This did not work however. I have also tried calling view.setNeedsLayout() and view.LayoutIfNeeded(). Neither of these have any effect.
I could solve this problem by making the UISearchBar active in viewDidLoad but am looking for a less janky solution.
Thanks!
Well this was an interesting lesson in debugging UI issues.
I believe this was ultimately caused by the ViewController being set to size inferred and size fixed. On different iPad screen sizes (9.7" vs 12.9").
To resolve this I set the frame width of the search bar to the tableview below it. I'm not sure why the searchbarview size changed width since its constrained to leading and trailing edges (superview).
if UIDevice.current.userInterfaceIdiom == .pad {
self.resultSearchController.searchBar.frame = CGRect(x: 0, y: 0, width: Int(tableView.frame.width), height: 44)
}
Although this works it has the same issue if split view is used (for widths where a popover has room to display).
Further suggestions are welcome but this is a good start.
---Edit---
Unchecking "Resize View from NIB" under layout in the ViewController as well as setting size to Freeform and declaring a constant width resolved the issue of the VC resizing on iPad. From there I just set the frame of the search bar in viewDidLoad as follows:
if UIDevice.current.userInterfaceIdiom == .pad {
self.resultSearchController.searchBar.frame = CGRect(x: 0, y: 0, width: 375, height: 44)
}
Seems to work for all devices regardless of split view or not. There probably is a better way to do this without detecting iPads. Im thinking I'm missing a setting in Interface Builder.