UIBarButtonItem在用作左侧或右侧导航栏项目时,自定义视图未在iOS 7上正确对齐

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UIBarButtonItem在用作左侧或右侧导航栏项目时,自定义视图未在iOS 7上正确对齐相关的知识,希望对你有一定的参考价值。

以下代码通过ios 6运行:

UIButton *myButton = nil;
myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.bounds = CGRectMake(0,0,44,30);
// setup myButton's images, etc.

UIBarButtonItem *item = nil;
item = [[UIBarButtonItem alloc] initWithCustomView:customButton];

这是按钮应该如何对齐:

但是,在iOS 7上,按钮似乎从右侧或左侧偏移了太多像素:

如何才能使我的自定义条形按钮项目正确对齐?

答案

适用于iOS11!

您可以使用负灵活空格和rightBarButtonItems属性而不是rightBarButtonItem:

UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
spacer.width = -10; // for example shift right bar button to the right

self.navigationItem.rightBarButtonItems = @[spacer, yourBarButton];
另一答案

我想出了jaredsinclair的缩短版本的方法:

- (UIEdgeInsets)alignmentRectInsets {
    return [self isLeftButton] ? UIEdgeInsetsMake(0, 9.0f, 0, 0) : UIEdgeInsetsMake(0, 0, 0, 9.0f); 
}

- (BOOL)isLeftButton {
    return self.frame.origin.x < (self.superview.frame.size.width / 2);
}

奇迹般有效。

另一答案

在ios7中,您可以添加一个虚拟的barbuttonitem来固定左侧空间,您应该首先添加虚拟,对于最后一个

左边的示例,您应该在设置原始项目后添加此项,或者如果您使用storyboard设置按钮,则应在viewdidload中添加。

NSMutableArray *buttons = [[NSMutableArray alloc] init];
UIBarButtonItem *spacerItem = [[UIBarButtonItem alloc] init];
[buttons addObject:spacerItem];
for(UIBarButtonItem *item in self.leftBarButtonItems){
    [buttons addObject:item];
}
[self setLeftBarButtonItems:[NSArray arrayWithArray:buttons] animated:NO];
另一答案

更改UIButton的以下内容

控制 - >对齐 - >水平对齐右对齐

另一答案

它只是简单地调整imageEdgeInsets来修复这个bug。

试试这个。

    UIButton *actionBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
    [actionBtn setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
    [actionBtn addTarget:self action:@selector(goToSetting) forControlEvents:UIControlEventTouchUpInside];
    actionBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 9, 0, -9);

    UIBarButtonItem *profileBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:actionBtn];
    self.topViewController.navigationItem.rightBarButtonItems = @[profileBarButtonItem];
另一答案

在iOS 11中测试过

 public lazy var navigationBackBarButton : UIBarButtonItem = {

        let backBarButtonIcon = <Image Literal here>
        let backBarButton = UIBarButtonItem(image: backBarButtonIcon, style: .plain, target: self, action: #selector(self.backBarButtonTouched(_:)))
        backBarButton.imageInsets = UIEdgeInsets(top: 0.0, left: -9.0, bottom: 0.0, right: 0.0)
        return backBarButton

    }()
另一答案

2018年,iOS 11 +,Swift 4.x,这对我有用。

结合最佳答案:

属性

internal lazy var button_Favorite: UIButton = {
    let button = UIButton(type: .custom)
    button.setImage(.favNormal, for: .normal)
    button.contentHorizontalAlignment = .right
    button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -9.0)
    return button
}()

viewDidLoad

    let barButton = UIBarButtonItem(customView: self.button_Favorite)
    self.button_Favorite.frame = CGRect(x: 0, y: 0, width: 40.0, height: 44.0)
    let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
    negativeSpacer.width = -10.0
    self.navigationItem.rightBarButtonItems = [negativeSpacer, barButton]
另一答案

为了解决这个bug,你必须继承UIButton,以便你可以覆盖alignmentRectInsets。根据我的测试,您需要返回具有正向右偏移或正向左偏移的UIEdgeInsets,具体取决于按钮位置。这些数字对我来说毫无意义(根据常识,其中至少有一个应该是否定的),但这实际上是有效的:

- (UIEdgeInsets)alignmentRectInsets {
    UIEdgeInsets insets;
    if (IF_ITS_A_LEFT_BUTTON) {
        insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
    } 
    else { // IF_ITS_A_RIGHT_BUTTON
        insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
    }
    return insets;
}

特别感谢@zev建议我尝试调整alignmentRectInsets。

另一答案

我已经尝试了上面的所有答案,但对我来说没有任何效果。这是有效的,如果有人需要这个:

(不需要子类化)

// Add your barButtonItem with custom image as the following 
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:self action:@selector(categoryButtonPressed)];
// set your custom image
[barButton setImage:categoryImage];
// finally do the magic
barButton.imageInsets = UIEdgeInsetsMake(0.0, -20, 0, 0);

- 看看结果。

注意左侧按钮和右侧按钮的空格(右侧按钮具有默认行为)

另一答案

好吧,我走了另一个“方向”。我通过使用iOS 7的Storyboard正确排列了所有内容(假设这是继续工作的方式)。然后使用describe子类方法,我用以下实现子类UIButton

- (UIEdgeInsets)alignmentRectInsets {
    UIEdgeInsets insets;
    if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
        if ([self isLeftButton]) {
            insets = UIEdgeInsetsMake(0, -10, 0, 0);
        } else {
            insets = UIEdgeInsetsMake(0, 0, 0, -10);
        }
    } else {
        insets = UIEdgeInsetsZero;
    }

    return insets;
}

- (BOOL)isLeftButton {
    return self.frame.origin.x < (self.superview.frame.size.width / 2);
}

因此,只有当设备处于iOS 7之前时,此代码才会运行。

感谢@jaredsinclair的见解!

另一答案

@jaredsinclair

这是我的代码。

// Create the tweetly button that will show settings
self.tweetlyDisplay = [NavButton buttonWithType:UIButtonTypeCustom];
[self.tweetlyDisplay setFrame:CGRectMake(0, 0, 90, 44)];
[self.tweetlyDisplay setBackgroundColor:[UIColor clearColor]];
[self.tweetlyDisplay setBackgroundImage:[UIImage imageNamed:@"settings.png"] forState:UIControlStateNormal];
[self.tweetlyDisplay setAdjustsImageWhenHighlighted:NO];
[self.tweetlyDisplay addTarget:self action:@selector(tweetlyPressed:) forControlEvents:UIControlEventTouchUpInside];

// Add the Tweetly button as the left bar button item
// This had a glitch that moves the image to the right somewhat
UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.tweetlyDisplay];
self.navigationItem.leftBarButtonItem = leftBarButton;

看到任何不对的东西?

这是结果。第二张图片不是那么可见,因为我不得不花时间截取屏幕截图并且它仍处于转换状态,但您可以清楚地看到它是如何不正确地抵消的。

良好的正常形象:

坏偏移图像:

大约半秒后,图像然后快速回到原始图像位置。

这是我的NavButton.h和.m的代码:

/**********************************************

 NavButton.h

 **********************************************/

#import <UIKit/UIKit.h>

@interface NavButton : UIButton

@end






/**********************************************

 NavButton.m

**********************************************/


#import "NavButton.h"

@implementation NavButton {

    int imageHeight;

}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code

        imageHeight = 44;

    }
    return self;
}

/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect
 {
 // Drawing code
 }
 */


- (UIEdgeInsets)alignmentRectInsets {
    UIEdgeInsets insets;
    if ([self isLeftButton]) {
        insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
    }
    else { // IF ITS A RIGHT BUTTON
        insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
    }
    return insets;
}


- (BOOL)isLeftButton {
    return self.frame.origin.x < (self.superview.frame.size.width / 2);
}


// THIS IS THE TRICK.  We make the height of the background rect match the image.
-(CGRect)backgroundRectForBounds:(CGRect)bounds
{
    CGRect bgRect = bounds;
    bgRect.origin.y = (bounds.size.height - imageHeight)/2.0f;
    bgRect.size.height = imageHeight;

    return bgRect;
}


@end
另一答案

这里可以找到一个没有跳跃按钮的更好的解决方案:

让 UIBarButtonItem 指向右侧的标准方法?

如何将几个 UIBarButtonItem 添加到导航栏?

UIBarButtonItem导航栏添加按钮

在右侧而不是左侧显示 UIToolbar 的 UIBarButtonItem

将 UIBarButtonItem 添加到 UIActionSheet 导航栏 (UIDatePicker)

如何在 UINavigationBar [iOS 7] 中编辑左、右 UIBarButtonItem 的空白