iOS - Place an image / container view above navigation bar - ios

For some design purpose, I need to place an image above the navigation bar.
Apple is pretty strict on not changing Nav Bar Height.. and I won't go there.
It's kind of a big app, so I won't have to change each controller apart.
My controllers are mostly presented in nav controllers, so I thought making an extension of UINavigationController will do the trick (so far it does). Anyone have ideas about this ?
extension UINavigationController {
override open func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 11.0, *) {
// This add space under my nav bar
self.additionalSafeAreaInsets = UIEdgeInsets(top: 80, left: 0, bottom: 0, right: 0)
// Need to find a way to move down my nav and add the logo above
}
}
}

The best way for you to place an image is in the Navigation title:
let logo = UIImage(named: "logo.png")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView
If you want something more customizable, I would suggest you create a View with a 0 constraint with SafeArea.

Add this views in your xib:
And create your navigationController in your class, like this:
import UIKit
class TopLogoViewController: UIViewController {
#IBOutlet weak var containerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let controller = UINavigationController(rootViewController: ViewController())
controller.navigationBar.backgroundColor = .green
controller.navigationBar.barTintColor = .green
controller.navigationBar.shadowImage = UIImage()
controller.navigationBar.isTranslucent = false
addChild(controller)
containerView.addSubview(controller.view)
controller.view.frame = containerView.bounds
controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
controller.didMove(toParent: self)
}
}

Related

Push ViewController subviews beneath NavigationBar when translucent is True, Programmatically

This question asked to be implemented in Swift 4, iOS 11
Is there any way to make every subview of ViewController's view to be pushed down when it is under UINavigationBar?
If navigation bar is NOT TRANSLUCENT the subview is under it. This is what I want.
Desired Result
But when navigation bar is TRANSLUCENT the subview is lying under it. I dont want it. I want the subview is pushed down just be like if navigation bar is not translucent.
Undesired Result
I create the view programmatically :
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.red
let navBar = (self.parent as? UINavigationController)?.navigationBar
navBar?.isTranslucent = true
}
func makeChildView() {
let myframe = CGRect(x: 0, y: 10, width: self.view.frame.width, height:
self.view.frame.height * 0.4)
let view = UIView(frame: myframe)
view.backgroundColor = UIColor.green
self.view.addSubview(view)
}
Using Autolayout
I am able to solve this problem using autolayout. But I just want to know how to achieve this result without autolayout if possible. Is there any other approach?
Swift 3.x
navBar?.isTranslucent = true
self.automaticallyAdjustsScrollViewInsets = false
Add this line & you are good to go.

Add Tab bar below Status bar using Material iOS

How to add tabbar below navigation bar using the Material's pod by CosmicMind
I was able to achieve this but it was touching the status bar like this
I want this to be below the status bar.
You can do with below code, add 20px StatusBar Height in Top(20)
fileprivate func prepareTabBar() {
tabBar = TabBar()
tabBar.delegate = self
tabBar.dividerColor = Color.grey.lighten4
tabBar.dividerAlignment = .bottom
tabBar.lineColor = Color.indigo.base
tabBar.lineAlignment = .bottom
tabBar.backgroundColor = Color.grey.lighten3
tabBar.buttons = buttons
view.layout(tabBar).horizontally().top(20)
}
You can create custom class of Tabbar and change frame at top:
class CustomTabBarController: UITabBarController {
#IBOutlet weak var myTabBarOutlet: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.shared.statusBarFrame.size.height
myTabBarOutlet.frame = CGRect(x: 0, y: myTabBarOutlet.frame.size.height, width: myTabBarOutlet.frame.size.width, height: myTabBarOutlet.frame.size.height)
}

iOS Navigation Item issues of extra padding top on landscape mode

There is extra padding top when my app in landscape.
Here is my code when create navigation bar programmatically.
Any advice to remove the padding top when in landscape mode?
let navigationBar = UINavigationBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 44)
navigationBar.backgroundColor = UIColor.redColor()
navigationBar.delegate = self;
let navigationItem = UINavigationItem()
navigationItem.title = "Title"
let btnLeft = UIButton(frame: CGRectMake(0, 0, 44, 44))
btnLeft.setImage(UIImage(named: “myImage.png"), forState: .Normal)
let leftButton = UIBarButtonItem()
leftButton.customView = btnLeft
navigationItem.leftBarButtonItem = leftButton
navigationBar.items = [navigationItem]
self.view.addSubview(navigationBar)
Snapshot from simulator (Landscape)
Snapshot from simulator (Portrait)
You should easily solve with this setting (in your viewDidLoad for example):
self.edgesForExtendedLayout = UIRectEdge.None
Alternative: You can put it also in your UINavigationController delegate method (if you have setted in your class your navigation delegate UINavigationControllerDelegate ) called willShowViewController:
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
viewController.edgesForExtendedLayout = UIRectEdge.None
}
If you work with UITableView you may also to do:
self.automaticallyAdjustsScrollViewInsets = false
You can also edit directly to the attribute inspector:
If anyone of these approaches don't work, by default your UINavigationBar have different heights based on your orientation. For example, the navigation bar is 44 points in portrait and 32 points in landscape.
A workaround can be:
// Create an IBOutlet of your navigationBar height constraint
#IBOutlet weak var navBarHeight: NSLayoutConstraint
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if self.view.bounds.size.height > self.view.bounds.size.width {
self.navBarHeight.constant = 44
} else {
self.navBarHeight.constant = 32
}
}

UISearchController search bar width not changing

Ran through a quick tutorial with search bars and figured that I could use searchBar.sizeToFit() to autosize the search bar, however the right end of the search bar still extends off of the screen.
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating, UISearchBarDelegate {
var searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchBar.delegate = self
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
}}
I've tried to manually set the frame with something like searchController.searchBar.frame = CGRectMake(0, 0, 200, 200) but the width remained off of the screen. The search bar does not exist in the storyboard, however the tableView does.
Needed to set autolayout constraints for the tableView that the search bar was a part of. Setting these fixed the sizing issues.
If you're using Auto layout, then use leading and trailing edges instead of width constraints.
Just click on Pin option given below and select top,leading(left) and trailing(right) constraints, then click on Add 3 constraints. Make sure "Constraint to margin" checkbox is unchecked. If the constraints satisfy, There will be no warning. Try changing the background color of your search bar to see its position on the screen.
If setting up auto layout constraints doesn't fix the problem, try calling searchController.searchBar.sizeToFit() in viewWillLayoutSubviews() rather than viewDidLoad(). This may help if the search bar is contained in a view other than the table header view.
Swift 4, works for all types of ViewControllers
After countless hours of trial and error here's what I came up for those who want to use it in code:
Set delegate
class SearchDatasourceController: UIViewController , UISearchBarDelegate { }
Set a customTitleView and the searchBar
IMPORTANT: set their frame
lazy var customTitleView: UIView = {
var view = UIView()
let frame = CGRect(x: 0, y: 0, width: 300, height: 44)
view.frame = frame
return view
}()
lazy var searchBar: UISearchBar = {
let searchBar = UISearchBar()
searchBar.placeholder = "Search"
searchBar.autocapitalizationType = .none
searchBar.backgroundImage = UIImage()
(searchBar.value(forKey: "searchField") as? UITextField)?.backgroundColor = UIColor(r: 230, g: 230, b: 230)
searchBar.delegate = self
searchBar.becomeFirstResponder()
let frame = CGRect(x: 0, y: 0, width: 300, height: 44)
searchBar.frame = frame
return searchBar
}()
in viewDidLoad add the customTitleView that holds the searchBar
override func viewDidLoad() {
super.viewDidLoad()
customTitleView.addSubview(searchBar)
navigationItem.titleView = customTitleView
searchBar.becomeFirstResponder()
}
add delegate method to listen for searches
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
print(searchText)
}
make sure you present your view controller on the navigation stack
func handleSearchBarButtonItemTapped() {
let controller = SearchDatasourceController()
navigationController?.pushViewController(controller, animated: true)
}

How to create a top TabBar on iOS?

Could you please tell me how to create a TabBar on the top for iPad in iOS, like in this picture?
The bottom TabBar is ok for me. But for the top TabBar, I am still getting stuck.
Note: I am using XCode6, Objective-C, iOS8, iPad screen
Thanks
I've created a new blank project and embeded the view controller in a navigation controller.
class ViewController: UIViewController {
var segmentedControl: UISegmentedControl!
var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
// Create the segmented control
self.segmentedControl = UISegmentedControl(items: ["Active", "Due", "Trash"])
self.segmentedControl.tintColor = UIColor.redColor()
self.segmentedControl.sizeToFit() // Replace this with any size you want
// Create the search bar
self.searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: 200, height: 32))
let rightBarButton = UIBarButtonItem(customView: self.searchBar)
// Finally add them to the navigation item
self.navigationItem.titleView = self.segmentedControl
self.navigationItem.rightBarButtonItem = rightBarButton
}
}

Resources