我想在两行文字的左边放置一个图标,以便在图像和文本开头之间有大约2-3个像素的空间。控件本身水平居中对齐(通过界面生成器设置)
该按钮将类似如下所示:
| |
|[Image] Add To |
| Favorites |我正在尝试用contentEdgeInset、imageEdgeInsets和titleEdgeInsets来配置它,但都无济于事。我知道负值会扩展边缘,而正值会缩小边缘以使其更接近中心。
我试过了:
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, -image.size.width, 0, 0)];
[button setImageEdgeInsets:UIEdgeInsetsMake(0, button.titleLabel.bounds.size.width, 0, 0)];但是这不能正确地显示它。我一直在调整这些值,但是从左边的-5到-10似乎并没有以预期的方式移动它。-10会将文本一直移到左边,所以我希望从左边移到一半,但事实并非如此。
insets背后的逻辑是什么?我不熟悉图像放置和相关术语。
我使用了这个SO问题作为参考,但我的值有些地方不正确。UIButton: how to center an image and a text using imageEdgeInsets and titleEdgeInsets?
发布于 2011-03-19 05:59:55
我同意关于imageEdgeInsets和titleEdgeInsets的文档应该更好,但我想出了如何在不经过反复试验的情况下获得正确的定位。
一般的想法在this question,但这是在你想要文本和图像居中的情况下。我们不希望图像和文本单独居中,我们希望图像和文本作为一个实体一起居中。这实际上是UIButton已经做的事情,所以我们只需要调整间距即可。
CGFloat spacing = 10; // the amount of spacing to appear between image and title
tabBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, spacing);
tabBtn.titleEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, 0);我还把它变成了UIButton的一个类别,这样就很容易使用了:
UIButton+Position.h
@interface UIButton(ImageTitleCentering)
-(void) centerButtonAndImageWithSpacing:(CGFloat)spacing;
@endUIButton+Position.m
@implementation UIButton(ImageTitleCentering)
-(void) centerButtonAndImageWithSpacing:(CGFloat)spacing {
self.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, spacing);
self.titleEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, 0);
}
@end所以现在我要做的就是:
[button centerButtonAndImageWithSpacing:10];每次我都能得到我想要的。不再手动处理边缘插图。
编辑:交换图像和文本
在评论中回应@Javal
使用同样的机制,我们可以交换图像和文本。要完成交换,只需使用负间距,但也要包括文本和图像的宽度。这将要求框架是已知的,并且已经执行了布局。
[self.view layoutIfNeeded];
CGFloat flippedSpacing = -(desiredSpacing + button.currentImage.size.width + button.titleLabel.frame.size.width);
[button centerButtonAndImageWithSpacing:flippedSpacing];当然,您可能希望为此创建一个很好的方法,可能会添加第二个类别方法,这将留给读者作为练习。
发布于 2014-08-29 08:26:02
我来参加这个聚会有点晚了,但我想我有一些有用的东西要补充。
RonLugge的回答很棒,但正如RonLugge提到的,它可以让按钮不再尊重sizeToFit,或者更重要的是,它可以使按钮在固有大小的情况下裁剪其内容。呀!
不过,首先,
和imageEdgeInsets titleEdgeInsets 的工作原理的简要说明:
在某种程度上,docs for imageEdgeInsets有以下内容要说:
使用此属性调整按钮图像的有效绘图矩形的大小和位置。您可以为四个插图(上、左、下、右)中的每一个指定不同的值。正值将缩小或嵌入该边缘-使其更靠近按钮的中心。负值将扩展或输出该边。
我相信这个文档是在想象按钮没有标题,只有一个图像的情况下编写的。考虑这种方式会更有意义,并且表现出UIEdgeInsets通常的行为方式。基本上,图像的框架(或标题,带有titleEdgeInsets)对于正向插入是向内移动的,而对于负向插入是向外移动的。
OK,那又怎样?
我快到了!下面是默认设置图片和标题(按钮边框是绿色的,只是为了显示它所在的位置):

当您想要图像和标题之间的间距,而不会导致两者都被压缩时,您需要设置四个不同的插入,在图像和标题上各设置两个。这是因为您不想更改这些元素框架的大小,而只想更改它们的位置。当你开始以这种方式思考时,对Kekoa的优秀类别所需的更改就变得清晰起来:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
}
@end但是等等,你说,当我这样做的时候,我得到了这个:

哦,是的!我忘了the docs警告过我这件事。他们说,在某种程度上:
此属性仅用于在布局期间定位图像。该按钮不使用此属性来确定
intrinsicContentSize和sizeThatFits:。
但是有一个属性可以提供帮助,那就是contentEdgeInsets。The docs说,在某种程度上:
该按钮使用此属性来确定intrinsicContentSize和sizeThatFits:。
听起来不错。因此,让我们再一次调整类别:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
self.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount);
}
@end你能得到什么?

在我看来是个赢家。
在Swift工作,根本不想做任何思考?以下是Swift中扩展的最终版本:
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
let isRTL = UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .rightToLeft
if isRTL {
imageEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: -insetAmount)
titleEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: insetAmount)
contentEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: -insetAmount)
} else {
imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: insetAmount)
titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: -insetAmount)
contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
}发布于 2015-06-26 00:20:57
另外,如果你想做一些类似的东西

你需要
1.将按钮的水平和垂直对齐方式设置为

UIImageEdgeInsetsCGSize buttonSize = button.frame.size;NSString *buttonTitle = button.titleLabel.text;CGSize titleSize = [buttonTitle sizeWithAttributes:@{ NSFontAttributeName : UIFont camFontZonaProBoldWithSize:12.f }];UIImage *buttonImage = button.imageView.image;CGSize buttonImageSize = buttonImage.size;CGFloat offsetBetweenImageAndText = 10;//图文按钮垂直间距setImageEdgeInsets:UIEdgeInsetsMake((buttonSize.height - (titleSize.height +buttonImageSize.height)/2- offsetBetweenImageAndText,(buttonSize.width - buttonImageSize.width) / 2,0,0);[按钮setTitleEdgeInsets:UIEdgeInsetsMake((buttonSize.height - (titleSize.height + buttonImageSize.height)) /2+ buttonImageSize.height + offsetBetweenImageAndText,titleSize.width +按钮imageEdgeInsets.left > buttonSize.width?-buttonImage.size.width + (buttonSize.width - titleSize.width) /2:(buttonSize.width - titleSize.width) /2- buttonImage.size.width,0,0)];
这将安排您的标题和图像在按钮上。
另外,请注意在每个relayout上更新此内容
斯威夫特
import UIKit
extension UIButton {
// MARK: - UIButton+Aligment
func alignContentVerticallyByCenter(offset:CGFloat = 10) {
let buttonSize = frame.size
if let titleLabel = titleLabel,
let imageView = imageView {
if let buttonTitle = titleLabel.text,
let image = imageView.image {
let titleString:NSString = NSString(string: buttonTitle)
let titleSize = titleString.sizeWithAttributes([
NSFontAttributeName : titleLabel.font
])
let buttonImageSize = image.size
let topImageOffset = (buttonSize.height - (titleSize.height + buttonImageSize.height + offset)) / 2
let leftImageOffset = (buttonSize.width - buttonImageSize.width) / 2
imageEdgeInsets = UIEdgeInsetsMake(topImageOffset,
leftImageOffset,
0,0)
let titleTopOffset = topImageOffset + offset + buttonImageSize.height
let leftTitleOffset = (buttonSize.width - titleSize.width) / 2 - image.size.width
titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset,
leftTitleOffset,
0,0)
}
}
}
}https://stackoverflow.com/questions/4564621
复制相似问题