Iphone 如何调整UIToolBar的左右填充

Iphone 如何调整UIToolBar的左右填充,iphone,objective-c,Iphone,Objective C,我用代码创建一个UIToolbar,用interface builder创建另一个UIToolbar。但是,发现两个工具栏具有不同的左、右填充,如下所示: 从界面生成器: 从代码: UIImage *buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0]; UIButton *btnTest = [UIButton buttonWithType:U

我用代码创建一个UIToolbar,用interface builder创建另一个UIToolbar。但是,发现两个工具栏具有不同的左、右填充,如下所示:

从界面生成器:

从代码:

UIImage *buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
UIButton *btnTest = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTest setBackgroundImage:buttonImage forState:UIControlStateNormal];
[btnTest setTitle:@"Back" forState:UIControlStateNormal];   
[btnTest.titleLabel setFont:[UIFont boldSystemFontOfSize:13]];  
[btnTest setBackgroundImage:[imgToolbarButton stretchableImageWithLeftCapWidth:5 topCapHeight:0]  forState:UIControlStateNormal];
[btnTest addTarget:self action:@selector(clearDateEdit:) forControlEvents:UIControlEventTouchUpInside];
btnTest.frame = CGRectMake(0.0, 0.0, 50, 30);
UIBarButtonItem *btnTestItem = [[UIBarButtonItem alloc] initWithCustomView:btnTest];
[self.toolbar setItems:[NSArray arrayWithObjects:btnTestItem,nil]];
[btnTestItem release];

我的问题是如何通过代码调整UIToolbar的左右填充

更新

我发现这个对齐问题只发生在UIButton的customView中的UIBarButtonItem上,UIBarButtonItem的对齐很好。你知道是什么原因造成的,或者是解决的

我现在能想到的唯一解决办法是手动设置帧。

使用此按钮

UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                                                           target:nil
                                                                           action:nil];

最后,为了定制uibarbuttonite的背景图像并适应对齐,我放弃了uibarbuttonite并手动添加UIButton

UIImage *buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
UIButton *btnTest = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTest setBackgroundImage:buttonImage forState:UIControlStateNormal];
[btnTest setTitle:@"Back" forState:UIControlStateNormal];   
[btnTest.titleLabel setFont:[UIFont boldSystemFontOfSize:13]];  
[btnTest setBackgroundImage:[imgToolbarButton stretchableImageWithLeftCapWidth:5 topCapHeight:0]  forState:UIControlStateNormal];
[btnTest addTarget:self action:@selector(clearDateEdit:) forControlEvents:UIControlEventTouchUpInside];
btnTest.frame = CGRectMake(0.0, 0.0, 50, 30);
[self.toolbar addSubview:btnTest];
[btnTestItem release];

我也有同样的问题,你可以用UIBarButtonSystemItemFixedSpace做一个巧妙的技巧,在第一个按钮之前和最后一个按钮之后添加一个负宽度的按钮,它会将按钮移动到边缘

例如,要删除右侧边距,请添加以下FixedSpace条项作为最后一项:

iOS 11至13的更新

  • Swift

    let negativeSeperator = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
    negativeSeperator.width = 12
    
    Swift版本中的宽度必须为正

  • var customButton = UIButton(type: .custom)
    customButton.overrideAlignmentRectInsets = UIEdgeInsets(top: 0, left: x, bottom: 0, right: -x) // you should do this in your own custom class
    customButton.translatesAutoresizingMaskIntoConstraints = false;
    
    var item = UIBarButtonItem(customView: customButton)
    
    var positiveSeparator = UIBarButtonItem(barButtonSystemItem:.fixedSpace, target: nil, action: nil)
    positiveSeparator.width = 8
    
    self.navigationItem.leftBarButtonItems = [positiveSeparator, item, ...]
    

  • Objc

    UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
    negativeSeparator.width = -12;
    
左边和右边的边距是12px


iOS7更新-iPhone上的利润率为16像素,iPad上的利润率为20像素

我遇到了同样的问题。最后,我通过将UIToolbar子类化并重写布局子视图方法解决了这个问题

- (void)layoutSubviews {

  [super layoutSubviews];

  if (leftItem_ && leftItem_.customView
      && [leftItem_.customView isKindOfClass:[UIButton class]]) {
    CGRect newFrame = leftItem_.customView.frame;
    newFrame.origin.x = 0;   // reset the original point x to 0; default is 12, wired number
    leftItem_.customView.frame = newFrame;    
  }

  if (rightItem_ && rightItem_.customView
      && [rightItem_.customView isKindOfClass:[UIButton class]]) {
    CGRect newFrame = rightItem_.customView.frame;
    newFrame.origin.x = self.frame.size.width - CGRectGetWidth(newFrame);
    rightItem_.customView.frame = newFrame;
  }

}

如果要使用customview(initWithCustomView),可以更改工具栏的偏移和宽度


我在尝试将工具栏作为UIButton的子视图居中时偶然发现了这一点。由于工具栏需要较小的宽度,最好的解决方案是在每一侧设置一个灵活的按钮:

UIBarButtonItem flexibleButtonItemLeft = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIBarButtonItem centeredButtonItem = ...

UIBarButtonItem flexibleButtonItemRight = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIToolbar toolbar = ...

toolbar.items = @[flexibleButtonItemLeft, centeredButtonItem, flexibleButtonItemRight];
在iOS 11之前 您有三种可能的解决方案:

  • 第一个是使用具有负宽度的固定空间项UIBarButtonItem(barButtonSystemItem:.fixedSpace…)
  • 另一个是覆盖自定义视图上的alignmentRectInsets
  • 最后一个选项是,如果使用UIButton作为项目的自定义视图,则可以覆盖ContentEdgeInSet和hitTest(\uWith:)
当然,第一种解决方案似乎比另一种更好

UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSeparator.width = -12;
如果您使用swift,代码将如下所示

var negativeSeparator = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
negativeSeparator.width = -12
iOS 11之后(包含iOS 11) 不幸的是,所有的解决方案都不能在iOS 11中使用

  • 第一种解决方案:设置负宽度不再有效
  • 第二种解决方案:覆盖alignmentRectInsets将导致部分项目不再接收触摸
  • 最后一个解决方案:我认为覆盖hitTest(:with:)不是一个好主意,请不要这样做
您还可以在上看到一些建议,但在查看所有注释后,您会发现关于此主题的建议是创建自定义UINavigationBar子类并执行一些复杂的操作

哦,我的上帝,我想做的就是改变填充,而不是导航栏

幸运的是,我们可以通过iOS 11中的一个技巧来实现这一点

我们开始: 1.创建自定义按钮
  • 将TranslatesAutoResizengMaskintoConstraints设置为false
  • 替代对齐矩形插入
    • 右侧项目使用UIEDGEINSET(顶部:0,左侧:-8,底部:0,右侧:8)
    • 左侧项目使用UIEDGEINSET(顶部:0,左侧:8,底部:0,右侧:-8) 如果您不知道AlignmentRectisets,可以先阅读

快速版本

var customButton = UIButton(type: .custom)
customButton.overrideAlignmentRectInsets = UIEdgeInsets(top: 0, left: x, bottom: 0, right: -x) // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = false;
var item = UIBarButtonItem(customView: customButton)
var positiveSeparator = UIBarButtonItem(barButtonSystemItem:.fixedSpace, target: nil, action: nil)
positiveSeparator.width = 8
self.navigationItem.leftBarButtonItems = [positiveSeparator, item, ...]
objective-c版本

UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
customButton.overrideAlignmentRectInsets = UIEdgeInsetsMake(0, x, 0, -x); // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = NO;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customButton]
UIBarButtonItem *positiveSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
positiveSeparator.width = 8;
self.navigationItem.leftBarButtonItems = @{positiveSeparator, item, ...}
2.使用自定义按钮创建项目 快速版本

var customButton = UIButton(type: .custom)
customButton.overrideAlignmentRectInsets = UIEdgeInsets(top: 0, left: x, bottom: 0, right: -x) // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = false;
var item = UIBarButtonItem(customView: customButton)
var positiveSeparator = UIBarButtonItem(barButtonSystemItem:.fixedSpace, target: nil, action: nil)
positiveSeparator.width = 8
self.navigationItem.leftBarButtonItems = [positiveSeparator, item, ...]
objective-c版本

UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
customButton.overrideAlignmentRectInsets = UIEdgeInsetsMake(0, x, 0, -x); // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = NO;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customButton]
UIBarButtonItem *positiveSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
positiveSeparator.width = 8;
self.navigationItem.leftBarButtonItems = @{positiveSeparator, item, ...}
3.创建宽度为正的固定空间类型UIBarButtonItem 设置一个正值,而不是负值

快速版本

var customButton = UIButton(type: .custom)
customButton.overrideAlignmentRectInsets = UIEdgeInsets(top: 0, left: x, bottom: 0, right: -x) // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = false;
var item = UIBarButtonItem(customView: customButton)
var positiveSeparator = UIBarButtonItem(barButtonSystemItem:.fixedSpace, target: nil, action: nil)
positiveSeparator.width = 8
self.navigationItem.leftBarButtonItems = [positiveSeparator, item, ...]
objective-c版本

UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
customButton.overrideAlignmentRectInsets = UIEdgeInsetsMake(0, x, 0, -x); // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = NO;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customButton]
UIBarButtonItem *positiveSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
positiveSeparator.width = 8;
self.navigationItem.leftBarButtonItems = @{positiveSeparator, item, ...}
4.将数组设置为leftitems或rightitems fixedSpace类型UIBarButton项必须是数组中的第一个元素

快速版本

var customButton = UIButton(type: .custom)
customButton.overrideAlignmentRectInsets = UIEdgeInsets(top: 0, left: x, bottom: 0, right: -x) // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = false;
var item = UIBarButtonItem(customView: customButton)
var positiveSeparator = UIBarButtonItem(barButtonSystemItem:.fixedSpace, target: nil, action: nil)
positiveSeparator.width = 8
self.navigationItem.leftBarButtonItems = [positiveSeparator, item, ...]
objective-c版本

UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
customButton.overrideAlignmentRectInsets = UIEdgeInsetsMake(0, x, 0, -x); // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = NO;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customButton]
UIBarButtonItem *positiveSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
positiveSeparator.width = 8;
self.navigationItem.leftBarButtonItems = @{positiveSeparator, item, ...}
做得好 完成所有步骤后,您将看到填充变小,并且键入区域似乎正确

如果你发现什么不对劲,请告诉我! 我会尽力回答你的问题

注 在iOS 11之前,您应该关心设备的屏幕宽度;如果屏幕为5.5英寸,则负极为-12磅,其他屏幕为-8磅

如果您在iOS 11上使用我的解决方案,您不需要关心设备屏幕,只需设置8pt, 您应该注意项目在导航栏中的位置(左侧或右侧),这将影响自定义视图的alignmentRectInsets

想要更多的水龙头吗 若要保证分接面积大于44*44,可以覆盖下面的方法

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    CGSize acturalSize = self.frame.size;
    CGSize minimumSize = kBarButtonMinimumTapAreaSize;
    CGFloat verticalMargin = acturalSize.height - minimumSize.height >= 0 ? 0 : ((minimumSize.height - acturalSize.height ) / 2);
    CGFloat horizontalMargin = acturalSize.width - minimumSize.width >= 0 ? 0 : ((minimumSize.width - acturalSize.width ) / 2);
    CGRect newArea = CGRectMake(self.bounds.origin.x - horizontalMargin, self.bounds.origin.y - verticalMargin, self.bounds.size.width + 2 * horizontalMargin, self.bounds.size.height + 2 * verticalMargin);
    return CGRectContainsPoint(newArea, point);
}

我认为一个棘手的方法是使用方面(或方法swizzling),如下所示:

[UINavigationBar aspect\u hookSelector:@selector(布局子视图),带有选项:AspectPositionAfter usingBlock:^(id信息){
UINavigationBar*bar=info.instance;
//[酒吧布局子视图];
if([bar是类的种类:[UINavigationBar类]]){
如果(@可用(iOS 11,*)){
bar.layoutMargins=UIEdgeInsetsZero;
用于(UIView*条形图中的子视图){
如果([NSStringFromClass([subview class])包含字符串:@“ContentView”]){
UIEdgeInsets oEdges=子视图。布局页边距;
subview.layoutMargins=UIEdgeInsetsMake(0,0,0,oEdges.right);
}
}
}
}
}错误:无];

这是一个很好的问题,即使提供了解决方案,它也没有解决iOS11上的问题

工作解决方案

如果创建
ui按钮的新扩展名

class BarButton: UIButton {

    override var alignmentRectInsets: UIEdgeInsets {
        return UIEdgeInsetsMake(0, 16, 0, 16)
    }

}
然后,当您在布局中使用它时:

lazy var btnLogin: BarButton = {
    let btn = BarButton(type: .custom)
    // Add your button settings

    btn.widthAnchor.constraint(equalToConstant: self.frame.size.width).isActive = true
    btn.heightAnchor.constraint(equalToConstant: 50).isActive = true
    btn.translatesAutoresizingMaskIntoConstraints = false
    return btn
}()
这解决了一个非常恼人的问题,如果你有任何问题的话