以下代码通过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上,该按钮似乎从右侧或左侧偏移了太多像素:
如何让自定义条形按钮项目正确对齐?
答案 0 :(得分:67)
直到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];
答案 1 :(得分:57)
为了修复此错误,您必须继承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。
答案 2 :(得分:28)
我已经尝试了上面的所有答案,但对我来说没有任何效果。这是有效的,如果有人需要这个:
(不需要子类化)
// 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);
- 看看结果。
注意左侧按钮和右侧按钮的空格( 右键具有默认行为)
答案 3 :(得分:10)
好的,我走了另一个“方向”。我通过使用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的见解!
答案 4 :(得分:3)
@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;
看到哪些不对?
结果如下。第二张图片不是那么明显,因为我不得不花时间截取屏幕截图并且它仍在转换中,但你可以清楚地看到它是如何被不正确地抵消。
良好的正常形象:
Bad Offset Image:
大约半秒钟后,图像会快速回到原始图像位置。
这是我的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
答案 5 :(得分:2)
这里可以找到一个没有跳跃按钮的更好的解决方案:
答案 6 :(得分:1)
不太喜欢子类化UIButton
或从Marius的答案中调来的方法:https://stackoverflow.com/a/19317105/287403
我只是使用了一个简单的包装器,并将按钮的框架的x向负方向移动,直到找到正确的位置。按钮敲击似乎也很好(尽管如果需要,您可以扩展按钮的宽度以匹配负偏移)。
以下是我用来生成新后退按钮的代码:
- (UIBarButtonItem *) newBackButton {
// a macro for the weak strong dance
@weakify(self);
UIButton *backButton = [[UIButton alloc] init];
[backButton setTitle:@"Back" forState:UIControlStateNormal];
backButton.titleLabel.font = [UIFont systemFontOfSize:17];
CGFloat width = [@"Back" boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:17]} context:nil].size.width + 27;
backButton.frame = CGRectMake(-17.5, 0, width + 17.5, 44);
[backButton setImage:[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"] forState:UIControlStateNormal];
[backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 14, 0, 0)];
[backButton setTitleColor:mTCOrangeColor forState:UIControlStateNormal];
backButton.contentEdgeInsets = UIEdgeInsetsZero;
backButton.imageEdgeInsets = UIEdgeInsetsZero;
[backButton addEventHandler:^(id sender) {
// a macro for the weak strong dance
@strongify(self);
// do stuff here
} forControlEvents:UIControlEventTouchUpInside];
UIView *buttonWrapper = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 44)];
[buttonWrapper addSubview:backButton];
return [[UIBarButtonItem alloc] initWithCustomView:buttonWrapper];
}
答案 7 :(得分:1)
我想添加到@jaredsinclair确认回答以下覆盖方法给那些在导航按钮中有文本和/或图像的人,否则文本和图像将不会对齐(只有背景图像):< / p>
- (UIEdgeInsets) titleEdgeInsets {
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
{
if (IF_ITS_A_LEFT_BUTTON) {
{
return UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
else
{ // IF_ITS_A_RIGHT_BUTTON
return UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
}
return [super titleEdgeInsets];
}
- (UIEdgeInsets)imageEdgeInsets {
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
{
if (IF_ITS_A_LEFT_BUTTON)
{
return UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
else
{ // IF_ITS_A_RIGHT_BUTTON
return UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
}
return [super imageEdgeInsets];
}
P.S。宏是:
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
答案 8 :(得分:0)
* 找到解决方案,请在答案结尾处阅读。 *
@jaredsinclair
我和Kyle Begeman有类似的案例
这是按钮
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
}
return self;
}
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")){
if ([self isLeftButton]) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
} else {
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
}else{
insets = UIEdgeInsetsZero;
}
return insets;
}
- (BOOL)isLeftButton {
return self.frame.origin.x < (self.superview.frame.size.width / 2);
}
我在这种情况下使用它
PBNavigationBarButton *dashboardButton = [PBNavigationBarButton buttonWithType:UIButtonTypeCustom];
UIImage *dashboardImage = [UIImage imageNamed:@"btn_dashboard.png"];
UIImage *dashboardImageHighlighted = [UIImage imageNamed:@"btn_dashboard_pressed.png"];
NSInteger halfImageWidth = ceilf([dashboardImage size].width/2.0f);
[dashboardButton setBackgroundImage:[dashboardImage stretchableImageWithLeftCapWidth:halfImageWidth topCapHeight:0] forState:UIControlStateNormal];
[dashboardButton setBackgroundImage:[dashboardImageHighlighted stretchableImageWithLeftCapWidth:halfImageWidth topCapHeight:0] forState:UIControlStateHighlighted];
[dashboardButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[dashboardButton sizeToFit];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:dashboardButton];
一切看起来都很棒,但是当我回到之前的VC时,按钮会重新定位。就像一个小小的跳跃。 对我来说,它确实会在一秒钟之后立即跳转。它发生在我从NavigationViewController进行popVC之后。
编辑:下面的答案,Marius的混合方法也帮助了我。
答案 9 :(得分:0)
我提出了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);
}
像魅力一样。
答案 10 :(得分:0)
左边的示例,您应该在设置原始项目后添加此项,或者如果您使用情节提要设置按钮,则应在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];
答案 11 :(得分:0)
更改UIButton
控制 - &gt;对齐 - &gt;水平到右对齐
答案 12 :(得分:0)
只需调整imageEdgeInsets
即可修复此错误。
试试这个。
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];
答案 13 :(得分:0)
在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
}()
答案 14 :(得分:0)
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]