改变UIBarButtonItem在UINavigationBar中的位置

时间:2022-09-26 11:18:23

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.

如何更改UINavigationBar中的UIBarButtonItem的位置?我希望我的按钮比正常位置高5px。

18 个解决方案

#1


33  

There is no particularly good way to do this. Your best bet if you really must is to subclass UINavigationBar, and override layoutSubviews to call [super layoutSubviews] and then find and reposition the button's view.

没有特别好的方法可以做到这一点。如果您确实必须这样做,那么最好的方法是子类化UINavigationBar,并覆盖layoutSubviews来调用[super layoutSubviews],然后找到并重新定位按钮的视图。

#2


115  

This code creates a back button for UINavigationBar with image background and custom position. The trick is to create an intermediate view and modify its bounds.

此代码为UINavigationBar创建一个后退按钮,该按钮具有图像背景和自定义位置。诀窍是创建一个中间视图并修改它的边界。

UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backBtnImage = [UIImage imageNamed:@"btn-back"];
UIImage *backBtnImagePressed = [UIImage imageNamed:@"btn-back-pressed"];
[backBtn setBackgroundImage:backBtnImage forState:UIControlStateNormal];
[backBtn setBackgroundImage:backBtnImagePressed forState:UIControlStateHighlighted];
[backBtn addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside];
backBtn.frame = CGRectMake(0, 0, 63, 33);
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 33)];
backButtonView.bounds = CGRectOffset(backButtonView.bounds, -14, -7);
[backButtonView addSubview:backBtn];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:backButtonView];
self.navigationItem.leftBarButtonItem = backButton;

#3


32  

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

#4


17  

For those of you developing for iOS 5 who stumbled across this and were discouraged... Try something like this:

对于那些正在开发iOS 5系统的人来说,他们发现了这一点,并感到气馁……试试这样:

float my_offset_plus_or_minus = 3.0f;

UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithTitle:@"title" 
                                                          style:UIBarButtonItemStyleDone
                                                          target:someObject action:@selector(someMessage)];

[item setBackgroundVerticalPositionAdjustment:my_offset_plus_or_minus forBarMetrics:UIBarMetricsDefault];

#5


12  

The best way is to subclass your UINavigationBar, as described here: https://*.com/a/17434530/1351190

最好的方法是子类化UINavigationBar,如这里所述:https://*.com/a/17434530/1351190。

Here is my example:

这是我的例子:

#define NAVIGATION_BTN_MARGIN 5

@implementation NewNavigationBar

- (void)layoutSubviews {

    [super layoutSubviews];

    UINavigationItem *navigationItem = [self topItem];

    UIView *subview = [[navigationItem rightBarButtonItem] customView];

    if (subview) {

        CGRect subviewFrame = subview.frame;
        subviewFrame.origin.x = self.frame.size.width - subview.frame.size.width - NAVIGATION_BTN_MARGIN;
        subviewFrame.origin.y = (self.frame.size.height - subview.frame.size.height) / 2;

        [subview setFrame:subviewFrame];
    }

    subview = [[navigationItem leftBarButtonItem] customView];

    if (subview) {

        CGRect subviewFrame = subview.frame;
        subviewFrame.origin.x = NAVIGATION_BTN_MARGIN;
        subviewFrame.origin.y = (self.frame.size.height - subview.frame.size.height) / 2;

        [subview setFrame:subviewFrame];
    }
}

@end

Hope it helps.

希望它可以帮助。

#6


6  

Try the code below,

试试下面的代码,

UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStyleDone target:self action:nil];
[button setBackgroundVerticalPositionAdjustment:-20.0f forBarMetrics:UIBarMetricsDefault];
[[self navigationItem] setRightBarButtonItem:button];

Its used to change the 'y' position in this code. Change the 'y' value (here it is -20.0f) according to your requirement. If the value is positive, it will down the button position. If the value is negative, it will up your button position.

它用于改变代码中的“y”位置。根据您的要求更改“y”值(这里是-20.0f)。如果值为正值,它将向下移动按钮位置。如果值为负,它将向上移动按钮位置。

#7


6  

I needed to set my button to be more over towards the right. Here's how I did it using UIAppearance in Swift. There's a vertical position property there as well so I imagine you can adjust in any direction.

我需要设置我的按钮,使其更向右。这是我在Swift中使用UIAppearance的方法。这里也有一个垂直位置属性所以我认为你可以任意调整方向。

UIBarButtonItem.appearance().setTitlePositionAdjustment(UIOffset.init(horizontal: 15, vertical: 0), forBarMetrics: UIBarMetrics.Default)

This seems much less invasive to me than messing with the frame directly or adding custom subviews.

对我来说,这似乎比直接打乱框架或添加自定义子视图要小得多。

#8


4  

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.)

如果您只是使用一个图像而不是默认的chrome,您可以使用负面的图像嵌套(设置在尺寸检查器中)来在UIBarButtonItem内移动您的图像(方便,因为默认情况下,水平填充会导致图像比您想要的更深入到内部)。您也可以使用image insets将图像定位到UIBarButtonItem边界之外,并且左侧按钮的整个邻近区域都是tappable,所以您不必担心它是否位于tap目标附近。(至少,在原因。)

#9


3  

The best solution I could find is to initialize a UIBarButtonItem with a subview that includes extra space to the left/right. That way you wont have to worry about subclassing, and changing the layout of other elements inside the navigation bar, such as the title.

我能找到的最好的解决方案是初始化一个UIBarButtonItem,它的子视图包含了左/右的额外空间。这样,您就不必担心子类化,以及更改导航栏中其他元素的布局,比如标题。

For example, to move a button 14 points to the left:

例如,将一个按钮向左移动14点:

UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, image.size.width + 14, image.size.height)];
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(-14, 0, image.size.width, image.size.height);
[button setImage:image forState:UIControlStateNormal];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button];

UIButton* button2 = [UIButton buttonWithType:UIButtonTypeCustom];
button2.frame = CGRectMake(0, 0, image.size.width + 14, image.size.height);
[button2 addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button2];

UIBarButtonItem* item = [[[self alloc] initWithCustomView:containerView] autorelease];

#10


2  

As @Anomie said, we need to subclass UINavigationBar, and override layoutSubviews().

正如@Anomie所说,我们需要对UINavigationBar进行子类化,并重写layoutSubviews()。

This will place all right bar button items firmly attached to the right side of the navigation bar (as opposed to being slightly left-adjusted by default):

这将把所有右栏按钮项牢牢地附着在导航栏的右边(而不是默认稍微左调整):

class AdjustedNavigationBar: UINavigationBar {

    override func layoutSubviews() {
        super.layoutSubviews()

        if let rightItems = topItem?.rightBarButtonItems where rightItems.count > 1 {
            for i in 0..<rightItems.count {
                let barButtonItem = rightItems[i]
                if let customView = barButtonItem.customView {
                    let frame = customView.frame
                    customView.frame = CGRect(x: UIApplication.sharedApplication().windows.last!.bounds.size.width-CGFloat(i+1)*44, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
                }

            }
        }
    }
}

The only place to set the UINavigationBar property of UINavigationController is in its init(), like so:

设置UINavigationController的UINavigationBar属性的惟一位置是它的init(),如下所示:

let controllerVC = UINavigationController(navigationBarClass: AdjustedNavigationBar.self, toolbarClass: nil)
controllerVC.viewControllers = [UIViewController()]

The second line sets the root view controller of UINavigationController. (Since we cannot set it via init(rootViewController:)

第二行设置UINavigationController的根视图控制器。(因为我们不能通过init设置它(rootViewController:)

#11


2  

Swift 3.1

斯威夫特3.1

let cancelBarButtonItem = UIBarButtonItem()
cancelBarButtonItem.setBackgroundVerticalPositionAdjustment(4, for: .default)
vc.navigationItem.setLeftBarButton(cancelBarButtonItem, animated: true)

#12


2  

  • Swift 3
  • 斯威夫特3
  • custom navigation bar height
  • 自定义导航栏的高度
  • no title jumping
  • 无标题跳

Step 1: Set title position using Appearance API. For example, in AppDelegate's didFinishLaunchingWithOptions

步骤1:使用外观API设置标题位置。例如,在AppDelegate的didFinishLaunchingWithOptions中

UINavigationBar.appearance().setTitleVerticalPositionAdjustment(-7, for: .default)

Step 2: Subclass UINavigationBar

步骤2:子类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)
            }
        }
    }
}

#13


2  

Here's Adriano's solution using Swift 3. It was the only solution that worked for me and I tried several.

这是阿德里亚诺用Swift 3的解决方案。这是唯一对我有效的解决办法,我试了好几次。

  let suggestImage  = UIImage(named: "menu.png")!
    let suggestButton = UIButton(frame: CGRect(x:0, y:0, width:34, height:20))
    suggestButton.setBackgroundImage(suggestImage, for: .normal)
    suggestButton.addTarget(self, action: #selector(self.showPopover(sender:)), for:.touchUpInside)
    suggestButton.transform = CGAffineTransform(translationX: 0, y: -8)
    // 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.leftBarButtonItem = suggestButtonItem

#14


2  

In my case

在我的例子中

  1. change barbuttonItem's frame to customize spaces

    更改barbuttonItem的框架以定制空间

  2. Add, Remove barButtonItems dynamically.

    动态添加、删除把。

  3. change tint colors by tableview's contentOffset.y

    根据tableview的contentOffset.y改变颜色

like this 改变UIBarButtonItem在UINavigationBar中的位置 改变UIBarButtonItem在UINavigationBar中的位置

像这样

改变UIBarButtonItem在UINavigationBar中的位置 改变UIBarButtonItem在UINavigationBar中的位置

If your minimum target is iOS 11, you can change the barButton frames in the viewDidLayoutSubviews

如果您的最小目标是ios11,您可以更改viewdidlayoutsubview中的barButton框架

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Change the navigationBar item frames
    if let customView = wishButton.customView?.superview {
        customView.transform = CGAffineTransform(translationX: 7.0, y: 0)
    }

    if let customView = gourmetCountButton.customView?.superview {
        customView.transform = CGAffineTransform(translationX: 9.0, y: 0)
    }
}

But, it's Only worked on iOS 11.

但是,它只适用于iOS 11。

I also tried using the fixedSpace. But It didn't work in multiple navigationBarButton items.

我还尝试了使用fixedSpace。但它不能在多个navigationBarButton条目中工作。

 let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
    space.width = -10

So, I changed customView's width to adjust horizontal space.

因此,我改变了customView的宽度来调整水平空间。

This is one of the my barButtonItem class

这是我的barButtonItem类之一

final class DetailShareBarButtonItem: UIBarButtonItem {

// MARK: - Value
// MARK: Public
***// Change the width to adjust space***
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 32.0, height: 30.0))

override var tintColor: UIColor? {
    didSet {
        button.tintColor = tintColor
    }
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setButton()
}

required override init() {
    super.init()
    setButton()
}


// MARK: - Function
// MARK: Private
private func setButton() {
    // Button
    button.setImage( #imageLiteral(resourceName: "navibarIcShare02White").withRenderingMode(.alwaysTemplate), for: .normal)
    button.tintColor              = .white
    button.imageEdgeInsets        = UIEdgeInsetsMake(0, 1.0, 1.0, 0)
    button.imageView?.contentMode = .scaleAspectFill

    let containerView = UIView(frame: button.bounds)
    containerView.backgroundColor = .clear
    containerView.addSubview(button)
    customView = containerView
}
}

This is the result.

这是结果。

I tested on iOS 9 ~ 11, (Swift 4)

我在ios9 ~ 11上测试过(Swift 4)

改变UIBarButtonItem在UINavigationBar中的位置

#15


1  

Init UIBarButtonItem with custom view and overload layoutSubviews in custom view, like this

在自定义视图中使用自定义视图和重载layoutSubviews的Init UIBarButtonItem,就像这样。

-(void) layoutSubviews {
  [super layoutSubviews];
  CGRect frame = self.frame;
  CGFloat offsetY = 5;
  frame.origin.y = (44 - frame.size.height) / 2 - offsetY;
  self.frame = frame;
}

#16


1  

You can always do adjustments using Insets on the button. For example,

你可以在按钮上使用Insets进行调整。例如,

UIButton *toggleBtn =  [UIButton buttonWithType:UIButtonTypeCustom];
[toggleBtn setFrame:CGRectMake(0, 0, 20, 20)];
[toggleBtn addTarget:self action:@selector(toggleView) forControlEvents:UIControlEventTouchUpInside];

[toggleBtn setImageEdgeInsets:((IS_IPAD)? UIEdgeInsetsMake(0,-18, 0, 6) : UIEdgeInsetsMake(0, -3, 0, -3))];

UIBarButtonItem *toggleBtnItem = [[UIBarButtonItem alloc] initWithCustomView: toggleBtn];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:searchBtnItem, toggleBtnItem, nil];

It works for me.

它适合我。

#17


0  

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.

这里有一个简单的解决方案,足以满足我的需要。我在UINavigationBar的右边添加了一个info按钮,但是默认情况下它太靠近边缘了。通过扩展框架的宽度,我可以创建右边需要的额外间距。

 UIButton *info = [UIButton buttonWithType:UIButtonTypeInfoLight];
 CGRect frame = info.frame;
 frame.size.width += 20;
 info.frame = frame;
 myNavigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]initWithCustomView:info]autorelease];

#18


0  

I found the solution of this problem by making adjustment in the Image Edge Insets of the custom button. I had the requirement in the app to increase the height of the navigation bar and after increasing the height makes the rightBarButtonItem and leftBarButtonItem images unpositioned problem.

我通过调整自定义按钮的图像边缘嵌套找到了这个问题的解决方案。我在app中有要求增加导航条的高度,增加了高度后,右barbuttonitem和leftBarButtonItem图像没有定位问题。

Find the code below:-

找到下面的代码:-

UIImage *image = [[UIImage imageNamed:@"searchbar.png"];
UIButton* searchbutton = [UIButton buttonWithType:UIButtonTypeCustom];
[searchbutton addTarget:self action:@selector(searchBar:) forControlEvents:UIControlEventTouchUpInside]; 
searchbutton.frame = CGRectMake(0,0,22, 22);
[searchbutton setImage:image forState:UIControlStateNormal];
[searchbutton setImageEdgeInsets:UIEdgeInsetsMake(-50, 0,50, 0)];
// Make BarButton Item
 UIBarButtonItem *navItem = [[UIBarButtonItem alloc] initWithCustomView:searchbutton];
self.navigationItem.rightBarButtonItem = navItem;

Hope this helps anyone.

希望这可以帮助任何人。

#1


33  

There is no particularly good way to do this. Your best bet if you really must is to subclass UINavigationBar, and override layoutSubviews to call [super layoutSubviews] and then find and reposition the button's view.

没有特别好的方法可以做到这一点。如果您确实必须这样做,那么最好的方法是子类化UINavigationBar,并覆盖layoutSubviews来调用[super layoutSubviews],然后找到并重新定位按钮的视图。

#2


115  

This code creates a back button for UINavigationBar with image background and custom position. The trick is to create an intermediate view and modify its bounds.

此代码为UINavigationBar创建一个后退按钮,该按钮具有图像背景和自定义位置。诀窍是创建一个中间视图并修改它的边界。

UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backBtnImage = [UIImage imageNamed:@"btn-back"];
UIImage *backBtnImagePressed = [UIImage imageNamed:@"btn-back-pressed"];
[backBtn setBackgroundImage:backBtnImage forState:UIControlStateNormal];
[backBtn setBackgroundImage:backBtnImagePressed forState:UIControlStateHighlighted];
[backBtn addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside];
backBtn.frame = CGRectMake(0, 0, 63, 33);
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 33)];
backButtonView.bounds = CGRectOffset(backButtonView.bounds, -14, -7);
[backButtonView addSubview:backBtn];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:backButtonView];
self.navigationItem.leftBarButtonItem = backButton;

#3


32  

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

#4


17  

For those of you developing for iOS 5 who stumbled across this and were discouraged... Try something like this:

对于那些正在开发iOS 5系统的人来说,他们发现了这一点,并感到气馁……试试这样:

float my_offset_plus_or_minus = 3.0f;

UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithTitle:@"title" 
                                                          style:UIBarButtonItemStyleDone
                                                          target:someObject action:@selector(someMessage)];

[item setBackgroundVerticalPositionAdjustment:my_offset_plus_or_minus forBarMetrics:UIBarMetricsDefault];

#5


12  

The best way is to subclass your UINavigationBar, as described here: https://*.com/a/17434530/1351190

最好的方法是子类化UINavigationBar,如这里所述:https://*.com/a/17434530/1351190。

Here is my example:

这是我的例子:

#define NAVIGATION_BTN_MARGIN 5

@implementation NewNavigationBar

- (void)layoutSubviews {

    [super layoutSubviews];

    UINavigationItem *navigationItem = [self topItem];

    UIView *subview = [[navigationItem rightBarButtonItem] customView];

    if (subview) {

        CGRect subviewFrame = subview.frame;
        subviewFrame.origin.x = self.frame.size.width - subview.frame.size.width - NAVIGATION_BTN_MARGIN;
        subviewFrame.origin.y = (self.frame.size.height - subview.frame.size.height) / 2;

        [subview setFrame:subviewFrame];
    }

    subview = [[navigationItem leftBarButtonItem] customView];

    if (subview) {

        CGRect subviewFrame = subview.frame;
        subviewFrame.origin.x = NAVIGATION_BTN_MARGIN;
        subviewFrame.origin.y = (self.frame.size.height - subview.frame.size.height) / 2;

        [subview setFrame:subviewFrame];
    }
}

@end

Hope it helps.

希望它可以帮助。

#6


6  

Try the code below,

试试下面的代码,

UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStyleDone target:self action:nil];
[button setBackgroundVerticalPositionAdjustment:-20.0f forBarMetrics:UIBarMetricsDefault];
[[self navigationItem] setRightBarButtonItem:button];

Its used to change the 'y' position in this code. Change the 'y' value (here it is -20.0f) according to your requirement. If the value is positive, it will down the button position. If the value is negative, it will up your button position.

它用于改变代码中的“y”位置。根据您的要求更改“y”值(这里是-20.0f)。如果值为正值,它将向下移动按钮位置。如果值为负,它将向上移动按钮位置。

#7


6  

I needed to set my button to be more over towards the right. Here's how I did it using UIAppearance in Swift. There's a vertical position property there as well so I imagine you can adjust in any direction.

我需要设置我的按钮,使其更向右。这是我在Swift中使用UIAppearance的方法。这里也有一个垂直位置属性所以我认为你可以任意调整方向。

UIBarButtonItem.appearance().setTitlePositionAdjustment(UIOffset.init(horizontal: 15, vertical: 0), forBarMetrics: UIBarMetrics.Default)

This seems much less invasive to me than messing with the frame directly or adding custom subviews.

对我来说,这似乎比直接打乱框架或添加自定义子视图要小得多。

#8


4  

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.)

如果您只是使用一个图像而不是默认的chrome,您可以使用负面的图像嵌套(设置在尺寸检查器中)来在UIBarButtonItem内移动您的图像(方便,因为默认情况下,水平填充会导致图像比您想要的更深入到内部)。您也可以使用image insets将图像定位到UIBarButtonItem边界之外,并且左侧按钮的整个邻近区域都是tappable,所以您不必担心它是否位于tap目标附近。(至少,在原因。)

#9


3  

The best solution I could find is to initialize a UIBarButtonItem with a subview that includes extra space to the left/right. That way you wont have to worry about subclassing, and changing the layout of other elements inside the navigation bar, such as the title.

我能找到的最好的解决方案是初始化一个UIBarButtonItem,它的子视图包含了左/右的额外空间。这样,您就不必担心子类化,以及更改导航栏中其他元素的布局,比如标题。

For example, to move a button 14 points to the left:

例如,将一个按钮向左移动14点:

UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, image.size.width + 14, image.size.height)];
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(-14, 0, image.size.width, image.size.height);
[button setImage:image forState:UIControlStateNormal];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button];

UIButton* button2 = [UIButton buttonWithType:UIButtonTypeCustom];
button2.frame = CGRectMake(0, 0, image.size.width + 14, image.size.height);
[button2 addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button2];

UIBarButtonItem* item = [[[self alloc] initWithCustomView:containerView] autorelease];

#10


2  

As @Anomie said, we need to subclass UINavigationBar, and override layoutSubviews().

正如@Anomie所说,我们需要对UINavigationBar进行子类化,并重写layoutSubviews()。

This will place all right bar button items firmly attached to the right side of the navigation bar (as opposed to being slightly left-adjusted by default):

这将把所有右栏按钮项牢牢地附着在导航栏的右边(而不是默认稍微左调整):

class AdjustedNavigationBar: UINavigationBar {

    override func layoutSubviews() {
        super.layoutSubviews()

        if let rightItems = topItem?.rightBarButtonItems where rightItems.count > 1 {
            for i in 0..<rightItems.count {
                let barButtonItem = rightItems[i]
                if let customView = barButtonItem.customView {
                    let frame = customView.frame
                    customView.frame = CGRect(x: UIApplication.sharedApplication().windows.last!.bounds.size.width-CGFloat(i+1)*44, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
                }

            }
        }
    }
}

The only place to set the UINavigationBar property of UINavigationController is in its init(), like so:

设置UINavigationController的UINavigationBar属性的惟一位置是它的init(),如下所示:

let controllerVC = UINavigationController(navigationBarClass: AdjustedNavigationBar.self, toolbarClass: nil)
controllerVC.viewControllers = [UIViewController()]

The second line sets the root view controller of UINavigationController. (Since we cannot set it via init(rootViewController:)

第二行设置UINavigationController的根视图控制器。(因为我们不能通过init设置它(rootViewController:)

#11


2  

Swift 3.1

斯威夫特3.1

let cancelBarButtonItem = UIBarButtonItem()
cancelBarButtonItem.setBackgroundVerticalPositionAdjustment(4, for: .default)
vc.navigationItem.setLeftBarButton(cancelBarButtonItem, animated: true)

#12


2  

  • Swift 3
  • 斯威夫特3
  • custom navigation bar height
  • 自定义导航栏的高度
  • no title jumping
  • 无标题跳

Step 1: Set title position using Appearance API. For example, in AppDelegate's didFinishLaunchingWithOptions

步骤1:使用外观API设置标题位置。例如,在AppDelegate的didFinishLaunchingWithOptions中

UINavigationBar.appearance().setTitleVerticalPositionAdjustment(-7, for: .default)

Step 2: Subclass UINavigationBar

步骤2:子类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)
            }
        }
    }
}

#13


2  

Here's Adriano's solution using Swift 3. It was the only solution that worked for me and I tried several.

这是阿德里亚诺用Swift 3的解决方案。这是唯一对我有效的解决办法,我试了好几次。

  let suggestImage  = UIImage(named: "menu.png")!
    let suggestButton = UIButton(frame: CGRect(x:0, y:0, width:34, height:20))
    suggestButton.setBackgroundImage(suggestImage, for: .normal)
    suggestButton.addTarget(self, action: #selector(self.showPopover(sender:)), for:.touchUpInside)
    suggestButton.transform = CGAffineTransform(translationX: 0, y: -8)
    // 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.leftBarButtonItem = suggestButtonItem

#14


2  

In my case

在我的例子中

  1. change barbuttonItem's frame to customize spaces

    更改barbuttonItem的框架以定制空间

  2. Add, Remove barButtonItems dynamically.

    动态添加、删除把。

  3. change tint colors by tableview's contentOffset.y

    根据tableview的contentOffset.y改变颜色

like this 改变UIBarButtonItem在UINavigationBar中的位置 改变UIBarButtonItem在UINavigationBar中的位置

像这样

改变UIBarButtonItem在UINavigationBar中的位置 改变UIBarButtonItem在UINavigationBar中的位置

If your minimum target is iOS 11, you can change the barButton frames in the viewDidLayoutSubviews

如果您的最小目标是ios11,您可以更改viewdidlayoutsubview中的barButton框架

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Change the navigationBar item frames
    if let customView = wishButton.customView?.superview {
        customView.transform = CGAffineTransform(translationX: 7.0, y: 0)
    }

    if let customView = gourmetCountButton.customView?.superview {
        customView.transform = CGAffineTransform(translationX: 9.0, y: 0)
    }
}

But, it's Only worked on iOS 11.

但是,它只适用于iOS 11。

I also tried using the fixedSpace. But It didn't work in multiple navigationBarButton items.

我还尝试了使用fixedSpace。但它不能在多个navigationBarButton条目中工作。

 let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
    space.width = -10

So, I changed customView's width to adjust horizontal space.

因此,我改变了customView的宽度来调整水平空间。

This is one of the my barButtonItem class

这是我的barButtonItem类之一

final class DetailShareBarButtonItem: UIBarButtonItem {

// MARK: - Value
// MARK: Public
***// Change the width to adjust space***
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 32.0, height: 30.0))

override var tintColor: UIColor? {
    didSet {
        button.tintColor = tintColor
    }
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setButton()
}

required override init() {
    super.init()
    setButton()
}


// MARK: - Function
// MARK: Private
private func setButton() {
    // Button
    button.setImage( #imageLiteral(resourceName: "navibarIcShare02White").withRenderingMode(.alwaysTemplate), for: .normal)
    button.tintColor              = .white
    button.imageEdgeInsets        = UIEdgeInsetsMake(0, 1.0, 1.0, 0)
    button.imageView?.contentMode = .scaleAspectFill

    let containerView = UIView(frame: button.bounds)
    containerView.backgroundColor = .clear
    containerView.addSubview(button)
    customView = containerView
}
}

This is the result.

这是结果。

I tested on iOS 9 ~ 11, (Swift 4)

我在ios9 ~ 11上测试过(Swift 4)

改变UIBarButtonItem在UINavigationBar中的位置

#15


1  

Init UIBarButtonItem with custom view and overload layoutSubviews in custom view, like this

在自定义视图中使用自定义视图和重载layoutSubviews的Init UIBarButtonItem,就像这样。

-(void) layoutSubviews {
  [super layoutSubviews];
  CGRect frame = self.frame;
  CGFloat offsetY = 5;
  frame.origin.y = (44 - frame.size.height) / 2 - offsetY;
  self.frame = frame;
}

#16


1  

You can always do adjustments using Insets on the button. For example,

你可以在按钮上使用Insets进行调整。例如,

UIButton *toggleBtn =  [UIButton buttonWithType:UIButtonTypeCustom];
[toggleBtn setFrame:CGRectMake(0, 0, 20, 20)];
[toggleBtn addTarget:self action:@selector(toggleView) forControlEvents:UIControlEventTouchUpInside];

[toggleBtn setImageEdgeInsets:((IS_IPAD)? UIEdgeInsetsMake(0,-18, 0, 6) : UIEdgeInsetsMake(0, -3, 0, -3))];

UIBarButtonItem *toggleBtnItem = [[UIBarButtonItem alloc] initWithCustomView: toggleBtn];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:searchBtnItem, toggleBtnItem, nil];

It works for me.

它适合我。

#17


0  

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.

这里有一个简单的解决方案,足以满足我的需要。我在UINavigationBar的右边添加了一个info按钮,但是默认情况下它太靠近边缘了。通过扩展框架的宽度,我可以创建右边需要的额外间距。

 UIButton *info = [UIButton buttonWithType:UIButtonTypeInfoLight];
 CGRect frame = info.frame;
 frame.size.width += 20;
 info.frame = frame;
 myNavigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]initWithCustomView:info]autorelease];

#18


0  

I found the solution of this problem by making adjustment in the Image Edge Insets of the custom button. I had the requirement in the app to increase the height of the navigation bar and after increasing the height makes the rightBarButtonItem and leftBarButtonItem images unpositioned problem.

我通过调整自定义按钮的图像边缘嵌套找到了这个问题的解决方案。我在app中有要求增加导航条的高度,增加了高度后,右barbuttonitem和leftBarButtonItem图像没有定位问题。

Find the code below:-

找到下面的代码:-

UIImage *image = [[UIImage imageNamed:@"searchbar.png"];
UIButton* searchbutton = [UIButton buttonWithType:UIButtonTypeCustom];
[searchbutton addTarget:self action:@selector(searchBar:) forControlEvents:UIControlEventTouchUpInside]; 
searchbutton.frame = CGRectMake(0,0,22, 22);
[searchbutton setImage:image forState:UIControlStateNormal];
[searchbutton setImageEdgeInsets:UIEdgeInsetsMake(-50, 0,50, 0)];
// Make BarButton Item
 UIBarButtonItem *navItem = [[UIBarButtonItem alloc] initWithCustomView:searchbutton];
self.navigationItem.rightBarButtonItem = navItem;

Hope this helps anyone.

希望这可以帮助任何人。