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
}
}
Related
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)
}
}
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.
How do I get the frame of a navigationItem's titleView in the coordinate system of the viewcontroller's view?
if let navBarHeight = navigationController?.navigationBar.frame.height,
let navBarWidth = navigationController?.navigationBar.frame.width {
myCustomTitleView.frame = CGRect(x: 0, y: 0, width: navBarWidth, height: navBarHeight)
navigationItem.titleView = myCustomTitleView
}
However, when I check myCustomTitleView's frame origin, I get (0, 0).
I then tried to translate this origin to the viewcontroller's view. what I got was (0,-44), which accounts for the navigation bar height but not for the x-offset.
let originInVCView = view.convert(myCustomTitleView.frame.origin, from: myCustomTitleView)
This can't be right as the titleView obviously has an offset (space for the back button).
How do I correctly extract the translated titleView origin?
You want to make sure you have set the navigation item in viewDidLoad() first. Otherwise it will be nil.
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(image: UIImage(named: "MY_IMAGE"))
navigationItem.titleView = imageView
When done you can get the frame in the VC's viewDidAppear where the view has been laid out:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let nItemFrame = navigationItem.titleView?.frame //<<<---
}
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)
}
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
}
}