i have a custom tab bar controller, that i want to add 2 buttons to. 1 enlarged centre button and 1 button on the left to create a side out burger menu that is launched from the tab bar instead instead of the top navigation bar.
i was going to try and get the tab bar height programatically so i can set the button heights ect from that. so i read up and tried the following code which does not work.
self.tabBarController?.tabBar.frame.size.height
i read somewhere else that the tabbar is always a fixed 49 pixels regardless of device?
if that is the case is it safe to use something like:
menuButtonFrame.origin.y = self.view.bounds.height - (CGFloat(49) - menuButtonFrame.size.height) / 2
to set the position of my button? (the black box) its not positions right just yet
also wondering what the default value for the tabbar button is?
Create a UIView Like this and set the height of the center item as your wish.
And then in TabbarView Controller. add this view to the tabbar View Like this.
UITabBar.appearance().shadowImage = UIImage()
customNavBar = NSBundle.mainBundle().loadNibNamed("CustomTabBarView", owner: self, options: nil)[0] as! UIView
bdNavBar.translatesAutoresizingMaskIntoConstraints = false
self.tabBar.addSubview(customNavBar)
And then add Constraints to the custom Tabbar.
self.view.addConstraint(NSLayoutConstraint(item: customNavBar, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: customNavBar, attribute: .Right, relatedBy: .Equal, toItem: self.view, attribute: .Right, multiplier: 1.0, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: customNavBar, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0))
bdNavBar.addConstraint(NSLayoutConstraint(item: customNavBar, attribute: NSLayoutAttribute.Height, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 50))
self.tabBar.bringSubviewToFront(customNavBar)
Related
I want to place header view on top of screen with NSLayoutConstraint (I must use NSLayoutConstraint). When I do it like in below code, view places corruptly in somewhere else and also controllers background color turns black and nothing works. Where am I doing wrong?
I searched below posts for not opening a duplicate post but nothing fixed it:
Programmatically creating constraints bound to view controller margins
Programmatically Add CenterX/CenterY Constraints
EDIT: This controller is inside navigation controller but I'm not sure If It is related.
override func viewDidLoad(){
self.view.backgroundColor = UIColor.white
boxView.backgroundColor = Color.Common.welcomeScreenBackgroundColor.withAlphaComponent(0.5)
boxView.translatesAutoresizingMaskIntoConstraints = false
self.view.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubView(boxView)
}
override func viewDidLayoutSubviews() {
//Header = 20 from left edge of screen
let cn1 = NSLayoutConstraint(item: boxView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 0)
//Header view trailing end is 20 px from right edge of the screen
let cn2 = NSLayoutConstraint(item: boxView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1.0, constant: 0)
//Header view height = constant 240
let cn3 = NSLayoutConstraint(item: boxView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant:240)
//Header view vertical padding from the top edge of the screen = 20
let cn5 = NSLayoutConstraint(item: boxView, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: 0)
self.view.addConstraints([cn1,cn2,cn3,cn5])
}
The problem was setting translatesAutoresizingMaskIntoConstraints to false on Superview. So I deleted the;
self.view.translatesAutoresizingMaskIntoConstraints = false
and this solves the problem. I think this causes app creates constraint for superview.
So what i m trying to achieve is I want to add a view between a tableview and the navigation bar. The hierarchy would be like:
Top-NavigationBar-betweenView-tableView-Bottom.
I have tried something like this, but the betweenView does not go under the navigation bar, and the tableView has a weird blank space above it. Anyone have any idea? Thank you!
let betweenView = searchController.searchBar
self.view.addSubview(betweenView)
let upperConstraint = NSLayoutConstraint(item: betweenView, attribute: .top, relatedBy: .equal, toItem: self.tableView, attribute: .top, multiplier: 1, constant: (self.navigationController?.navigationBar.frame.height)!)
let lowerConstraint = NSLayoutConstraint(item: self.tableView, attribute: .top, relatedBy: .equal, toItem: searchView, attribute: .bottom, multiplier: 1, constant: 0)
self.view.addConstraint(upperConstraint)
self.view.addConstraint(lowerConstraint)
You'll want to do 2 things here:
1) Layout the constraint for the search view to the top layout guide. This will move your search view below the navigation bar on a per need basis:
let upperConstraint = NSLayoutConstraint(item: searchView, attribute: .top, relatedBy: .equal, toItem: topLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0)
2) You need to make sure the table does not automatically adjust the scrolling to the navigation controller:
tableView.automaticallyAdjustsScrollViewInsets = false
I have these views, both are the same, i want to add them programmatically so i want to add constraints programmatically, i've managed to do same using storyboard but i want to use code for this.
i want to add margins to these views so that first one is at the top, next one is below the first one and so,
i've wrote code like this:
self.view.addConstraint(
NSLayoutConstraint(
item: secondView,
attribute: .Top,
relatedBy: .Equal,
toItem: firstView,
attribute: .Top,
multiplier: 1.0,
constant: 0
))
first view has the constraint in which toItem is current view controller and it works, but the second view does not work this way, it just draws it on top of the first view, i want it to be below it, only way i can do this is in constant: 0 enter the height of the view, which i don't like
any suggestions?
The code you supplied is 99% right but
self.view.addConstraint(
NSLayoutConstraint(
item: secondView,
attribute: .Top,
relatedBy: .Equal,
toItem: firstView,
attribute: .Top,
multiplier: 1.0,
constant: 0
))
Your attaching the top of secondView to the top of firstView so they would be on top instead you want the top of secondView to the bottom of firstView.
self.view.addConstraint(
NSLayoutConstraint(
item: secondView,
attribute: .Top,
relatedBy: .Equal,
toItem: firstView,
attribute: .Bottom, <----------
multiplier: 1.0,
constant: 0
))
The constant is the distance.
Various answers to this are on Stack Overflow, but I can't seem to get it to work.
I want a UIPickerView to have a width equal to 90 % of the superview's frame width, a height to be 35 % of superview's
frame height, centred horizontally
and to have it's top equal to the top of the superview but below the navigation bar (this last constraint is what I'm having difficulty with).
At the moment, the top of the picker view seems to be behind the navigation bar. I've tried adding edgesForExtendedLayout = .Top and extendedLayoutIncludesOpaqueBars = false so that the picker view is under the navigation bar. I've also tried adding a constant to the constraint
NSLayoutConstraint(item: somePickerView, attribute: .Top, relatedBy: .Equal, toItem: superview, attribute: .TopMargin, multiplier: 1.0, constant: navigationController?.navigationBar.frame.height) but this didn't move the picker view enough.
class ViewController: UIViewController {
let superview = self.view
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = .Top
extendedLayoutIncludesOpaqueBars = false
somePickerView = UIPickerView()
somePickerView.translatesAutoresizingMaskIntoConstraints = false
superview.addSubview(somePickerView)
superview.addConstraint(NSLayoutConstraint(item: somePickerView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1, constant: superview.frame.width * 0.90))
superview.addConstraint(NSLayoutConstraint(item: somePickerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1, constant: superview.frame.height * 0.35))
superview.addConstraint(NSLayoutConstraint(item: somePickerView, attribute: .CenterX, relatedBy: .Equal, toItem: superview, attribute: .CenterX, multiplier: 1, constant: 0))
// the following constraint's not working as expected:
superview.addConstraint(NSLayoutConstraint(item: somePickerView, attribute: .Top, relatedBy: .Equal, toItem: superview, attribute: .TopMargin, multiplier: 1.0, constant: 0))
}
}
any advice for the constraint to place the picker view at the top but below the navigation bar?
I'm adding a subview to navigationbar , problem is that im unable to add constraints to it .Im getting crash like this
terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with items ; value: 0.000000> and > because they have no common ancestor. Does the constraint reference items in different view hierarchies? That's illegal.'
The code used is below
//create a slider and add it to the view
let slider = UISlider()
self.navigationController?.navigationBar.addSubview(slider)
//pin the slider 20 points from the left edge of the the superview
//from the left edge of the slider to the left edge of the superview
//superview X coord is at 0 therefore 0 + 20 = 20 position
let horizonalContraints = NSLayoutConstraint(item: slider, attribute:
.LeadingMargin, relatedBy: .Equal, toItem: view,
attribute: .LeadingMargin, multiplier: 1.0,
constant: 20)
//pin the slider 20 points from the right edge of the super view
//negative because we want to pin -20 points from the end of the superview.
//ex. if with of super view is 300, 300-20 = 280 position
let horizonal2Contraints = NSLayoutConstraint(item: slider, attribute:
.TrailingMargin, relatedBy: .Equal, toItem: view,
attribute: .TrailingMargin, multiplier: 1.0, constant: -20)
//pin 100 points from the top of the super
let pinTop = NSLayoutConstraint(item: slider, attribute: .Top, relatedBy: .Equal,
toItem: view, attribute: .Top, multiplier: 1.0, constant: 100)
//when using autolayout we an a view, MUST ALWAYS SET setTranslatesAutoresizingMaskIntoConstraints
//to false.
slider.translatesAutoresizingMaskIntoConstraints = false
slider.backgroundColor = UIColor.redColor()
//IOS 8
//activate the constrains.
//we pass an array of all the contraints
NSLayoutConstraint.activateConstraints([horizonalContraints, horizonal2Contraints,pinTop])
The above code works fine if i use the line view.addSubview(slider)
instead of
self.navigationController?.navigationBar.addSubview(slider)
But the idea is to add constraints on a subview on navigation bar .
Any thoughts are welcome
As the exception already stated, the navigationBar is not a subview of 'view'. It belongs to the navigationcontroller.
What you could do is to use the navbar's superview:
let slider = UISlider()
self.navigationController?.navigationBar.addSubview(slider)
let targetView = self.navigationController?.navigationBar.superview
let horizonalContraints = NSLayoutConstraint(item: slider, attribute:
.LeadingMargin, relatedBy: .Equal, toItem: targetView,
attribute: .LeadingMargin, multiplier: 1.0,
constant: 20)
let horizonal2Contraints = NSLayoutConstraint(item: slider, attribute:
.TrailingMargin, relatedBy: .Equal, toItem: targetView,
attribute: .TrailingMargin, multiplier: 1.0, constant: -20)
let pinTop = NSLayoutConstraint(item: slider, attribute: .Top, relatedBy: .Equal,
toItem: targetView, attribute: .Top, multiplier: 1.0, constant: 10)
slider.translatesAutoresizingMaskIntoConstraints = false
slider.backgroundColor = UIColor.redColor()
NSLayoutConstraint.activateConstraints([horizonalContraints, horizonal2Contraints,pinTop])
That removes the exception and might look like it does what you want, but it is definitely not a good solution. If you want the slider inside the navbar, add it to the navigationitem instead. If you want it bellow the navbar, add it to your View and set a constraint to the top layout guide.