How to show a custom view on top of navigation bar in Swift? - ios

So the way I understand navigation bar (navigation item) is that it has three locations you can modify, which is left (leftBarButtomItem), middle (titleView), and right (rightBarButtonItem).
Now what I'm going to achieve is that I want to just add a simple progress bar line at the very bottom of navigation bar, but still inside navigation bar. I want to make this like an extension of navigation bar that I can reuse on other screens. But I want that left, middle, and right "views" are still working like usual. e.g. I don't want that if I change the title view content manually in other view controller, then the line disappears / stops working for that other view controller. So this will feel like an independent overlay added on top of navigation bar as subview, separated from leftBarButtonItem, titleView, and rightBarButtonView, sort to speak.
Is it possible to do that in navigation item?

This is a example of how to add a Image instead of a Title String
fileprivate func setupTitle(){
let logo = UIImage(named: "my_incredible_logo")
let imageView = UIImageView(image:logo)
imageView.contentMode = .scaleAspectFit
self.navigationItem.titleView = imageView
self.navigationController?.navigationBar.prefersLargeTitles = false
}

Related

Static/fixed Navigation Bar in iOS

I have a Navigation Controller and a Collection View under it inside my app. And there is a problem: I use large title inside my Navigation bar, so everything inside is not static. When I scroll the collection view cells, the title (I created it manually using UILabel() to move it as I want inside the navigation bar) and buttons move up and the navigation bar takes form of iOS 10 navigation bar, I mean its height. You can see it here:
The normal state of my Navigation Bar with "Prefer large titles" On:
It happens when I scroll my Collection View, everything goes up:
So the question is simple: how to make the force constant height for the navigation bar? I want it to become fixed even while scrolling. Are there any ideas? Is it possible?
And the second question, if the first is impossible: Another solution for my problem is to make the Navigation Bar with "Prefer large titles" Off bigger. I tried this code:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let height: CGFloat = 50 //whatever height you want to add to the existing height
let bounds = self.navigationController!.navigationBar.bounds
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height + height)
}
but it worked only for large titles. So how can I make the navigation bar bigger?
Yes, you can make it fixed. It will not scroll if the very first view in the view hierarchy is not a CollectionView/TableView (ScrollView).
Using Storyboard/Xib:
Consider the following image where a tableView and button are added in scene. Here the navigation bar will collapse on scroll of tableView because tableView is the very first view in viewController's containerView hierarchy attached to the navigation bar.
Now to make the navigation bar fixed, if we just change the order of tableView and button as below, it will disable the collapsing of navigation bar.
To change the order of the view, you have to click, hold and move up/down.
If you have only CollectionView in this scene then you can add a placeholder view at the top and set its height to zero as below,
Programmatically:
If you are setting up view's programmatically then you just need to add a placeholder view at the top or add tableView/collection after adding other views.
e.g,
self.view.addSubview(UIView(frame: .zero))
self.view.addSubview(tableView) // or collectionView

How to cover up status bar with subview?

So I have the subview (side menu) pulled out on top of the main view inside of a Navigation Controller. Is it possible to hide the status bar on the slide out menu but continue to show it on the main view?
Note: one view is currently on top of the other
override var prefersStatusBarHidden: Bool {
return true
}
try this ... Can't Hide Status Bar—Swift 3,
You can hide status bar in a condition.. You need to add another Window Object over the status bar.
let stautsBarWindow = UIWindow(frame: UIScreen.main.bounds)
stautsBarWindow.backgroundColor = UIColor.clear
stautsBarWindow.rootViewController = yourSideMenuViewController
stautsBarWindow.windowLevel = UIWindowLevelStatusBar
stautsBarWindow.isHidden = false
This will create another window object at the top of your status bar. So just slide it pretty left side so that you can see only half of it/ reduce its width to half of the screen so that you can only see half visible area and show full viewController inside this area. Which ever logic you think is right just use that.

View doesn't go under status bar and status bar is black

I'm hiding the Navigation Bar on one of the screens, and if is set:
navigationController?.navigationBarHidden = true
The status bar becomes black. Also, the image doesn't fit all the screen (see the screenshot).
If I comment this line, Navigation bar stays on screen, and the status bar is white.
Full code:
override func viewWillAppear(animated: Bool) {
navigationController?.navigationBarHidden = true
navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
navigationController?.navigationBar.translucent = true
navigationController?.navigationBar.backgroundColor = UIColor.clearColor()
navigationController?.view.backgroundColor = UIColor.clearColor()
All constraints of ImageView are set to 0 and it's set to fill the screen:
So, I want to put ImageView under the status bar and make the status bar icons/text white. What I'm doing wrong?
You're not doing anything "wrong". You have set the top of the image view to the bottom of the view controller's top layout guide. Well, that's the bottom of the status bar — exactly where you see the top of the image view.
If you want the image view to underlap the status bar, its top needs to be pinned to the top of the main view, not the top layout guide.
And if you want the status bar to change text color, you need to implement preferredStatusBarStyle to return .LightContent. If this means that the result of preferredStatusBarStyle has changed, you would need to call setNeedsStatusBarAppearanceUpdate to alert the runtime to this fact.
To place the image view under the status bar, and have the image view fill the UIViewControllers view:
Clear all constraints for the image view
Add a constraint to set the image view to have the same width as the parent view
Add a constraint to set the image view to have the same height as the parent view
Pin the image view to the nearest neighbor as shown below. Add the constraints
The final constraints will look like the following:

Autolayout with Navigation Bar - Remove Specific Constraint

I'm building an application for iOS, which is using a navigation controller. I want to put a view in the titleView, and have it fill the whole width of the navigation bar.
I'm calling setupNavBar in viewDidLoad of the view controller that is embedded in the navigation controller. Here is how I do:
func setupNavBar() {
let navBar = navigationController?.navigationBar
// navBar!.translatesAutoresizingMaskIntoConstraints = false
// navBar!.frame.size.height = CGFloat(100)
let searchBar = UIView(frame: navBar!.frame)
searchBar.bounds = CGRectMake(0, 0, navBar!.frame.width, navBar!.frame.height)
searchBar.backgroundColor = UIColor.brownColor()
navigationItem.titleView = searchBar
}
But the view (brown - "searchBar"), doesn't cover the full navigation bar:
So I figured out that the problem was related to Autoresizing and Constraints, because if I call navBar!.translatesAutoresizingMaskIntoConstraints = false, I can freely set the sizes of views frame, so there must be some constraints that change the view's bounds. But I would like to keep as much of the autolayout behaviour as possible.
Is there a way to only change the contraints on the titleView?
I'm doing everything programmatically, I don't use the storyboard or xib's!
EDIT:
But it doesn't seem like there is any constraints on either navigationItem or navBar:
for someObject in navigationItem.titleView!.constraints {
print(someObject)
}
It doesn't print any constraints. neither if I use navBar.constraints!
EDIT 2:
I have a screenshot from "View UI Hierarchy" from the debug navigator:
It seems that the view(brown) alligns with the Navigation Bar Back Indicator View, maybe this is a clue to what causes the problem?
How come the view is resized?
Two different suggestions here:
1. You can try the
navigationItem.titleView.sizeToFit()
Otherwise you could set the background colour of the navbar to brown as it appears you wish the brown bar to cover the entire width of the navbar. If you want to add other views on top of that you then can.
You could also try to make an outlet to the title view and add an NSLayoutConstraint using
navigationItem.titleView.addConstraint(NSLayoutConstraint: NSLayoutConstraint)
I am not entirely sure whether that will work, however.

Search bar bug - iOS

In my app I have this kind of bug:
When I scroll down, the content of table is seen above the search bar. What can be the reason?
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.searchBar.barTintColor = UIColor(red: 52.0/255.0, green: 73.0/255.0, blue: 94.0/255.0, alpha: 1.0)
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
self.tableView.reloadData()
}
The iOS Human Interface Guidelines list 3 methods to prevent content from showing through the status bar.
Use a navigation controller to display content. A navigation controller automatically displays a status bar background and it
ensures that its content views don’t appear behind the status bar. (To
learn more about navigation controllers, see Navigation Controllers.)
Create a nondistracting custom image—such as a gradient—and display it behind the status bar. To ensure that the image stays
behind the status bar, you could use a view controller to keep the
image above a scrolling view or you could use a scrolling view to keep
it pinned to the top.
Position content to avoid the status bar area (that is, the area defined by the app’s statusBarFrame property). If you do this, you
should use the window’s background color to provide a solid color
behind the status bar.
You should make the status bar not translucent.
The status bar's color is a property of UIApplication. You need to set it to a valid UIStatusBarStyle.
The new UISearchController has been designed to work with a UITableView and a UINavigationBar. Its functionality depends on your navigation bar being present. when the search bar has content in its text field, it will be latched on top of the page under the navigation bar. well, you don't have any navigation bar, it will latch to the top view guide and it always takes into account the status bar (if present) I guess the only way you can resolve your problem without an actual navigation bar is to add a view under status bar and make it opaque just like your search bar. it's a bit hacky but it's alright in my book.

Resources