如果我有一个使用自动布局排列的 UIButton,它的大小会很好地调整以适应它的内容。
如果我将图像设置为 button.image
,则内部尺寸似乎再次说明了这一点。
但是,如果我调整按钮的 titleEdgeInsets
,布局不会考虑这一点,而是会截断按钮标题。
如何确保按钮的固有宽度占插图?
https://i.stack.imgur.com/bFikp.png
编辑:
我正在使用以下内容:
[self.backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
目标是在图像和文本之间添加一些分隔。
titleEdgeInset
文档:The insets you specify are applied to the title rectangle after that rectangle has been sized to fit the button’s text. Thus, positive inset values may actually clip the title text.
因此,通过添加插图,您将强制按钮确定剪辑文本
您可以通过结合使用否定和肯定的标题和内容插入,在 Interface Builder 中使其工作(无需编写任何代码)。
https://i.stack.imgur.com/wnBnd.png
更新:Xcode 7 有一个错误,您无法在 Right
Inset 字段中输入负值,但您可以使用它旁边的步进控件来减少价值。 (谢谢斯图尔特)
这样做会在图像和标题之间增加 8pt 的间距,并将按钮的固有宽度增加相同的量。像这样:
https://i.stack.imgur.com/g5azb.png
您无需重写任何方法或设置任意宽度约束即可解决此问题。您可以在 Interface Builder 中完成所有操作,如下所示。
固有按钮宽度来自标题宽度加上图标宽度加上左右内容边缘插图。
如果按钮同时具有图像和文本,则它们作为一个组居中,中间没有填充。
如果您添加左侧内容插图,它是相对于文本计算的,而不是文本 + 图标。
如果您设置负左图像插入,图像被拉到左侧,但整体按钮宽度不受影响。
如果您设置负左图像插图,则实际布局使用该值的一半。因此,要获得 -20 点左插图,您必须在 Interface Builder 中使用 -40 点左插图值。
因此,您提供了一个足够大的左侧内容插图,以便为所需的左侧插图和图标和文本之间的内部填充创建空间,然后通过将您想要的图标和文本之间的填充量加倍来将图标向左移动。结果是一个具有相同左右内容插入的按钮,以及作为一组居中的文本和图标对,它们之间具有特定数量的填充。
一些示例值:
// Produces a button with the layout:
// |-20-icon-10-text-20-|
// AutoLayout intrinsic width works as you'd desire.
button.contentEdgeInsets = UIEdgeInsetsMake(10, 30, 10, 20)
button.imageEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0)
UIButton
的奇怪行为的合理性。
为什么不覆盖 UIView 上的 intrinsicContentSize
方法?例如:
- (CGSize) intrinsicContentSize
{
CGSize s = [super intrinsicContentSize];
return CGSizeMake(s.width + self.titleEdgeInsets.left + self.titleEdgeInsets.right,
s.height + self.titleEdgeInsets.top + self.titleEdgeInsets.bottom);
}
这应该告诉自动布局系统它应该增加按钮的大小以允许插入并显示全文。我不在自己的电脑上,所以我没有测试过这个。
intrinsicContentSize
是 UIView 上的方法,而不是 UIButton,因此您不会弄乱任何 UIButton 方法。 Apple 认为这不是问题:“重写此方法允许自定义视图与布局系统通信,它希望基于其内容的大小。” OP没有说任何关于不同按钮的信息,只是一个。
intrinsicContentSize
确实是 UIView 上的一个方法,而 UIButton 是 UIView 的子类,因此您当然可以重写此方法; Apple 的文档中没有任何内容表明您不应该这样做。只需使用 Maarten 的重写方法创建一个 UIButton 子类,并将 Interface Builder 中的 UIButton 更改为 YourUIButtonSubclass 类型,它就会完美地工作。
intrinsicContentSize
的 UIButton 应该在 titleEdgeInsets 中添加,我将向 Apple 提交一个错误。
您尚未指定如何设置插图,所以我猜您正在使用 titleEdgeInsets ,因为我看到您得到的效果相同。如果我改用 contentEdgeInsets ,它可以正常工作。
- (IBAction)ChangeTitle:(UIButton *)sender {
self.button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);
[self.button setTitle:@"Long Long Title" forState:UIControlStateNormal];
}
而对于 Swift 来说,它是这样工作的:
extension UIButton {
override open var intrinsicContentSize: CGSize {
let intrinsicContentSize = super.intrinsicContentSize
let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom
return CGSize(width: adjustedWidth, height: adjustedHeight)
}
}
爱你斯威夫特
这个线程有点老了,但我自己也遇到了这个问题,并且能够通过使用负插图来解决它。例如,在这里替换您想要的填充值:
UIButton* myButton = [[UIButton alloc] init];
// setup some autolayout constraints here
myButton.titleEdgeInsets = UIEdgeInsetsMake(-desiredBottomPadding,
-desiredRightPadding,
-desiredTopPadding,
-desiredLeftPadding);
结合正确的自动布局约束,您最终会得到一个包含图像和文本的自动调整大小按钮!如下所示,desiredLeftPadding
设置为 10。
https://i.stack.imgur.com/RVdm9.png
https://i.stack.imgur.com/s6lL8.png
您可以看到按钮的实际框架不包含标签(因为标签向右移动了 10 个点,超出了边界),但我们在文本和图片之间实现了 10 个点的填充。
我想在我的 UIButton 图标和标签之间添加一个 5pt 的空间。这就是我实现它的方式:
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
// more button config etc
infoButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 5);
infoButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 0, -5);
contentEdgeInsets、titleEdgeInsets 和 imageEdgeInsets 相互关联的方式需要从每个插图中进行一些取舍。因此,如果您在标题的左侧添加一些插图,则必须在右侧添加负插图并在内容右侧提供更多空间(通过正插图)。
通过添加正确的内容插图以匹配标题插图的移动,我的文本不会超出按钮的范围。
对于基于 pegpeg 的回答的 Swift 3:
extension UIButton {
override open var intrinsicContentSize: CGSize {
let intrinsicContentSize = super.intrinsicContentSize
let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom
return CGSize(width: adjustedWidth, height: adjustedHeight)
}
}
以上所有不适用于iOS 9+,我所做的是:
添加宽度约束(当按钮没有任何文本时为最小宽度。如果提供文本,按钮将自动缩放)
将关系设置为大于或等于
https://i.stack.imgur.com/Zafor.png
现在要在按钮周围添加边框,只需使用以下方法:
button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);
该选项在界面生成器中也可用。见插图。我将左右设置为 3。就像一个魅力。
https://i.stack.imgur.com/Nkmzv.png
我使用的解决方案是在按钮上添加宽度约束。然后在初始化的某个地方,在设置文本之后,像这样更新宽度约束:
self.buttonWidthConstraint.constant = self.shareButton.intrinsicContentSize.width + 8;
无论您的插图是什么,8 都在哪里。
constant
更新为新值......并知道按钮的内在内容大小何时如果没有子类化按钮,更改是困难的。
setNeedsUpdateConstraints
。然后您可以覆盖 updateConstraints
并从那里重新计算 buttonWidthConstraint
的常数。这不一定是最好的方法,但它对我来说已经足够好了。 YMMV ;)
Right
字段中的负值。