How can I change the position of a UIBarButtonItem in a UINavigationBar? I would like my button to be about 5px higher than its normal position.
If you're simply using an image and NOT the default chrome, you can use negative image insets (set in the size inspector) to move your image around inside the UIBarButtonItem (handy because by default the horizontal padding can result in the image being further to the inside than you want). You can use the image insets to position the image outside of the bounds of the UIBarButtonItem, as well, and the entire vicinity of the left-hand-side button is tappable, so you don't have to worry about ensuring it's positioned near a tap target. (at least, within reason.)
Affine transform can do what you need. In my case designer gave me 16x16 close icon and I want to create 44x44 tap area.
closeButton.transform = CGAffineTransform(translationX: (44-16)/2, y: 0)
closeButton.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 44, height: 44))
}
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: closeButton)
I solved using transform and custom view:
(Swift)
// create the button
let suggestImage = UIImage(named: "tab-item-popcorn-on")!.imageWithRenderingMode(.AlwaysOriginal)
let suggestButton = UIButton(frame: CGRectMake(0, 0, 40, 40))
suggestButton.setBackgroundImage(suggestImage, forState: .Normal)
suggestButton.addTarget(self, action: Selector("suggesMovie:"), forControlEvents:.TouchUpInside)
// here where the magic happens, you can shift it where you like
suggestButton.transform = CGAffineTransformMakeTranslation(10, 0)
// add the button to a container, otherwise the transform will be ignored
let suggestButtonContainer = UIView(frame: suggestButton.frame)
suggestButtonContainer.addSubview(suggestButton)
let suggestButtonItem = UIBarButtonItem(customView: suggestButtonContainer)
// add button shift to the side
navigationItem.rightBarButtonItem = suggestButtonItem
Step 1: Set title position using Appearance API. For example, in AppDelegate's didFinishLaunchingWithOptions
UINavigationBar.appearance().setTitleVerticalPositionAdjustment(-7, for: .default)
Step 2: Subclass UINavigationBar
class YourNavigationBar: UINavigationBar {
let YOUR_NAV_BAR_HEIGHT = 60
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width,
height: YOUR_NAV_BAR_HEIGHT)
}
override func layoutSubviews() {
super.layoutSubviews()
let navigationItem = self.topItem
for subview in subviews {
if subview == navigationItem?.leftBarButtonItem?.customView ||
subview == navigationItem?.rightBarButtonItem?.customView {
subview.center = CGPoint(x: subview.center.x, y: YOUR_NAV_BAR_HEIGHT / 2)
}
}
}
}
Swift 3.1
let cancelBarButtonItem = UIBarButtonItem()
cancelBarButtonItem.setBackgroundVerticalPositionAdjustment(4, for: .default)
vc.navigationItem.setLeftBarButton(cancelBarButtonItem, animated: true)
Here is a simple workaround that was sufficient for my needs. I added an info button on the right hand side of the UINavigationBar but by default it sits way too close to the edge. By extending the width of the frame I was able to create the extra spacing needed on the right.
UIButton *info = [UIButton buttonWithType:UIButtonTypeInfoLight];
CGRect frame = info.frame;
frame.size.width += 20;
info.frame = frame;
myNavigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]initWithCustomView:info]autorelease];