iOS 11 之前
您有三种可能的解决方案:
- 第一个是使用固定宽度为负的空间项 UIBarButtonItem(barButtonSystemItem: .fixedSpace ...)
- 另一个是在自定义视图上覆盖alignmentRectInsets
- 最后一个,如果你使用 UIButton 作为你项目的自定义视图,你可以覆盖 contentEdgeInsets 和 hitTest(_:with:)
当然,第一个解决方案似乎比其他解决方案更好
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会导致部分item不再接收触摸
- 最后一个解决方案:我认为覆盖 hitTest(_:with:) 不是一个好主意,请不要这样做!
您也可以在Developer Forums 上看到一些建议,但是当您查看所有评论后,您会发现有关此主题的建议是创建自定义 UINavigationBar 子类并做一些复杂的事情。
我的天啊,我想做的只是改变填充,而不是导航栏!
幸运的是,我们可以在 iOS 11 中使用一个技巧来做到这一点!
我们开始:
1。创建自定义按钮
- 将 translatesAutoresizingMaskIntoConstraints 设置为 false
- 覆盖alignmentRectInsets
- 右侧的项目使用 UIEdgeInsets(top: 0, left: -8, bottom: 0, right: 8)
- 左侧项目使用 UIEdgeInsets(top: 0, left: 8, bottom: 0, right: -8)
如果不知道alignmentRectInsets,可以先阅读this blog
快捷版
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;
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;
2。使用您的自定义按钮创建一个项目
快捷版
var item = UIBarButtonItem(customView: customButton)
objective-c 版本
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customButton]
3。创建一个宽度为 positive
的 fixedSpace 类型 UIBarButtonItem
设置一个正值,而不是负值
快捷版
var positiveSeparator = UIBarButtonItem(barButtonSystemItem:.fixedSpace, target: nil, action: nil)
positiveSeparator.width = 8
objective-c 版本
UIBarButtonItem *positiveSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
positiveSeparator.width = 8;
4。将数组设置为 leftitems 或 rightitems
fixedSpace 类型的 UIBarButton 项必须是数组中的第一个元素。
快捷版
self.navigationItem.leftBarButtonItems = [positiveSeparator, item, ...]
objective-c 版本
self.navigationItem.leftBarButtonItems = @{positiveSeparator, item, ...}
干得好
完成所有步骤后,您会看到内边距变小并且输入区域似乎正确!
如果您发现有问题,请告诉我!
我会尽力回答你的问题!
注意
在 iOS 11 之前,你应该关心设备的屏幕宽度;如果屏幕是5.5英寸,负片是-12pt,其他屏幕是-8pt。
如果你在 iOS 11 上使用我的解决方案,你不需要关心设备屏幕,只需设置 8pt,
您应该关心项目在导航栏中的位置,左侧或右侧,这将影响您自定义视图的对齐矩形插入
想要更多的点击区域
如果你想保证你的点击区域大于 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);
}