rei*_*man 158 objective-c uibutton ios
如果我只在一个按钮中放置一个图像并将imageEdgeInsets设置得更接近顶部,则图像保持居中并且所有图像都按预期工作:
[button setImage:image forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, 0.0)];
Run Code Online (Sandbox Code Playgroud)
如果我只在一个按钮中放置一个文本并将titleEdgeInsets设置得更接近底部,则文本保持居中并且所有文件都按预期工作:
[button setTitle:title forState:UIControlStateNormal];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, -30, 0.0)];
Run Code Online (Sandbox Code Playgroud)
但是,如果我将4条线放在一起,文本会干扰图像,并且两者都会失去中心对齐.
我的所有图像都有30像素的宽度,如果我在setTitleEdgeInsets的UIEdgeInsetMake的左参数中放入30,则文本再次居中.问题是图像永远不会居中,因为它似乎依赖于button.titleLabel大小.我已经尝试了许多计算按钮大小,图像大小,titleLabel大小,永远不会完全居中.
有人已经有同样的问题吗?
Jes*_*sen 408
对于它的价值,这里是一个通用的解决方案,将图像定位在文本上方,而不使用任何幻数.请注意,以下代码已过时,您应该使用以下某个更新版本:
// the space between the image and text
CGFloat spacing = 6.0;
// lower the text and push it left so it appears centered
// below the image
CGSize imageSize = button.imageView.frame.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
CGSize titleSize = button.titleLabel.frame.size;
button.imageEdgeInsets = UIEdgeInsetsMake(
- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
Run Code Online (Sandbox Code Playgroud)
以下版本包含支持iOS 7+的更改,这些更改已在下面的评论中推荐.我自己没有测试过这段代码,所以我不确定它是如何工作的,或者如果在以前版本的iOS下使用它会破坏它.
// the space between the image and text
CGFloat spacing = 6.0;
// lower the text and push it left so it appears centered
// below the image
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
button.imageEdgeInsets = UIEdgeInsetsMake(
- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
// increase the content height to avoid clipping
CGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;
button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);
Run Code Online (Sandbox Code Playgroud)
Swift版本
extension UIButton {
func alignVertical(spacing: CGFloat = 6.0) {
guard let imageSize = imageView?.image?.size,
let text = titleLabel?.text,
let font = titleLabel?.font
else { return }
titleEdgeInsets = UIEdgeInsets(
top: 0.0,
left: -imageSize.width,
bottom: -(imageSize.height + spacing),
right: 0.0
)
let titleSize = text.size(withAttributes: [.font: font])
imageEdgeInsets = UIEdgeInsets(
top: -(titleSize.height + spacing),
left: 0.0,
bottom: 0.0, right: -titleSize.width
)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0
contentEdgeInsets = UIEdgeInsets(
top: edgeOffset,
left: 0.0,
bottom: edgeOffset,
right: 0.0
)
}
}
Run Code Online (Sandbox Code Playgroud)
rei*_*man 59
发现如何.
首先,配置文本titleLabel
(因为样式,即粗体,斜体等).然后,使用setTitleEdgeInsets
考虑图像的宽度:
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont boldSystemFontOfSize:10.0]];
// Left inset is the negative of image width.
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, -image.size.width, -25.0, 0.0)];
Run Code Online (Sandbox Code Playgroud)
之后,使用setTitleEdgeInsets
考虑文本边界的宽度:
[button setImage:image forState:UIControlStateNormal];
// Right inset is the negative of text bounds width.
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, -button.titleLabel.bounds.size.width)];
Run Code Online (Sandbox Code Playgroud)
现在图像和文本将居中(在此示例中,图像显示在文本上方).
干杯.
alg*_*gal 20
您可以使用此Swift扩展程序来完成此操作,该扩展程序部分基于Jesse Crossen的答案:
extension UIButton {
func centerLabelVerticallyWithPadding(spacing:CGFloat) {
// update positioning of image and title
let imageSize = self.imageView.frame.size
self.titleEdgeInsets = UIEdgeInsets(top:0,
left:-imageSize.width,
bottom:-(imageSize.height + spacing),
right:0)
let titleSize = self.titleLabel.frame.size
self.imageEdgeInsets = UIEdgeInsets(top:-(titleSize.height + spacing),
left:0,
bottom: 0,
right:-titleSize.width)
// reset contentInset, so intrinsicContentSize() is still accurate
let trueContentSize = CGRectUnion(self.titleLabel.frame, self.imageView.frame).size
let oldContentSize = self.intrinsicContentSize()
let heightDelta = trueContentSize.height - oldContentSize.height
let widthDelta = trueContentSize.width - oldContentSize.width
self.contentEdgeInsets = UIEdgeInsets(top:heightDelta/2.0,
left:widthDelta/2.0,
bottom:heightDelta/2.0,
right:widthDelta/2.0)
}
}
Run Code Online (Sandbox Code Playgroud)
这定义了一个centerLabelVerticallyWithPadding
适当设置标题和图像插入的函数.
它还设置了contentEdgeInsets,我认为这是确保intrinsicContentSize
仍能正常工作所必需的,需要使用自动布局.
我相信所有UIButton子类的解决方案在技术上都是非法的,因为你不应该继承UIKit控件的子类.即,从理论上讲,它们可能会在未来版本中破裂.
Tho*_*eek 13
编辑:已更新为Swift 3
如果您正在寻找Jesse Crossen答案的Swift解决方案,您可以将其添加到UIButton的子类中:
override func layoutSubviews() {
let spacing: CGFloat = 6.0
// lower the text and push it left so it appears centered
// below the image
var titleEdgeInsets = UIEdgeInsets.zero
if let image = self.imageView?.image {
titleEdgeInsets.left = -image.size.width
titleEdgeInsets.bottom = -(image.size.height + spacing)
}
self.titleEdgeInsets = titleEdgeInsets
// raise the image and push it right so it appears centered
// above the text
var imageEdgeInsets = UIEdgeInsets.zero
if let text = self.titleLabel?.text, let font = self.titleLabel?.font {
let attributes = [NSFontAttributeName: font]
let titleSize = text.size(attributes: attributes)
imageEdgeInsets.top = -(titleSize.height + spacing)
imageEdgeInsets.right = -titleSize.width
}
self.imageEdgeInsets = imageEdgeInsets
super.layoutSubviews()
}
Run Code Online (Sandbox Code Playgroud)
这里有一些很好的例子,但在处理多行文本(文本换行)时,我无法在所有情况下都能使用它.为了最终使它工作,我结合了几种技术:
我上面用了Jesse Crossen的例子.但是,我修复了文本高度问题,并添加了指定水平文本边距的功能.允许文本换行时边距非常有用,因此它不会触及按钮的边缘:
// the space between the image and text
CGFloat spacing = 10.0;
float textMargin = 6;
// get the size of the elements here for readability
CGSize imageSize = picImage.size;
CGSize titleSize = button.titleLabel.frame.size;
CGFloat totalHeight = (imageSize.height + titleSize.height + spacing); // get the height they will take up as a unit
// lower the text and push it left to center it
button.titleEdgeInsets = UIEdgeInsetsMake( 0.0, -imageSize.width +textMargin, - (totalHeight - titleSize.height), +textMargin ); // top, left, bottom, right
// the text width might have changed (in case it was shortened before due to
// lack of space and isn't anymore now), so we get the frame size again
titleSize = button.titleLabel.bounds.size;
button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + spacing), 0.0, 0.0, -titleSize.width ); // top, left, bottom, right
Run Code Online (Sandbox Code Playgroud)确保设置要包装的文本标签
Run Code Online (Sandbox Code Playgroud)button.titleLabel.numberOfLines = 2; button.titleLabel.lineBreakMode = UILineBreakModeWordWrap; button.titleLabel.textAlignment = UITextAlignmentCenter;
这将主要工作.但是,我有一些按钮无法正确渲染图像.图像要么向右或向左移动(它没有居中).所以我使用了UIButton布局覆盖技术来强制imageView居中.
Run Code Online (Sandbox Code Playgroud)@interface CategoryButton : UIButton @end @implementation CategoryButton - (void)layoutSubviews { // Allow default layout, then center imageView [super layoutSubviews]; UIImageView *imageView = [self imageView]; CGRect imageFrame = imageView.frame; imageFrame.origin.x = (int)((self.frame.size.width - imageFrame.size.width)/ 2); imageView.frame = imageFrame; } @end
小智 9
我为@ TodCunningham的答案做了一个方法
-(void) AlignTextAndImageOfButton:(UIButton *)button
{
CGFloat spacing = 2; // the amount of spacing to appear between image and title
button.imageView.backgroundColor=[UIColor clearColor];
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
button.titleLabel.textAlignment = UITextAlignmentCenter;
// get the size of the elements here for readability
CGSize imageSize = button.imageView.frame.size;
CGSize titleSize = button.titleLabel.frame.size;
// lower the text and push it left to center it
button.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// the text width might have changed (in case it was shortened before due to
// lack of space and isn't anymore now), so we get the frame size again
titleSize = button.titleLabel.frame.size;
// raise the image and push it right to center it
button.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
}
Run Code Online (Sandbox Code Playgroud)
不要打架系统.如果你的布局变得太复杂而无法使用Interface Builder +或者一些简单的配置代码进行管理,那么可以使用更简单的方式手动完成布局layoutSubviews
- 这就是它的用途!其他一切都将成为黑客.
创建一个UIButton子类并覆盖其layoutSubviews
方法以编程方式对齐文本和图像.或者使用类似https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h的内容,以便您可以使用块实现layoutSubviews.
小智 6
子类UIButton
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat spacing = 6.0;
CGSize imageSize = self.imageView.image.size;
CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(self.frame.size.width, self.frame.size.height - (imageSize.height + spacing))];
self.imageView.frame = CGRectMake((self.frame.size.width - imageSize.width)/2, (self.frame.size.height - (imageSize.height+spacing+titleSize.height))/2, imageSize.width, imageSize.height);
self.titleLabel.frame = CGRectMake((self.frame.size.width - titleSize.width)/2, CGRectGetMaxY(self.imageView.frame)+spacing, titleSize.width, titleSize.height);
}
Run Code Online (Sandbox Code Playgroud)
其他答案没有错,但我只想注意,使用零行代码可以在Xcode中直观地完成相同的行为.如果您不需要计算值或使用storyboard/xib构建(否则应用其他解决方案),此解决方案非常有用.
注意 - 我确实理解OP的问题是需要代码的问题.我只是提供完整性的答案,并作为使用storyboards/xibs的逻辑替代品.
要使用边缘插入修改按钮的图像,标题和内容视图的间距,可以选择按钮/控件并打开属性检查器.向下滚动到检查器的中间,找到Edge insets的部分.
还可以访问和修改标题,图像或内容视图的特定边缘插入.
Jesse Crossen对Swift 4的更新答案:
extension UIButton {
func alignVertical(spacing: CGFloat = 6.0) {
guard let imageSize = self.imageView?.image?.size,
let text = self.titleLabel?.text,
let font = self.titleLabel?.font
else { return }
self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
let labelString = NSString(string: text)
let titleSize = labelString.size(withAttributes: [kCTFontAttributeName as NSAttributedStringKey: font])
self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: 0.0, right: -titleSize.width)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
}
}
Run Code Online (Sandbox Code Playgroud)
使用这种方式:
override func viewDidLayoutSubviews() {
button.alignVertical()
}
Run Code Online (Sandbox Code Playgroud)
extension UIButton {
func alignTextUnderImage() {
guard let imageView = imageView else {
return
}
self.contentVerticalAlignment = .Top
self.contentHorizontalAlignment = .Center
let imageLeftOffset = (CGRectGetWidth(self.bounds) - CGRectGetWidth(imageView.bounds)) / 2//put image in center
let titleTopOffset = CGRectGetHeight(imageView.bounds) + 5
self.imageEdgeInsets = UIEdgeInsetsMake(0, imageLeftOffset, 0, 0)
self.titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset, -CGRectGetWidth(imageView.bounds), 0, 0)
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
125581 次 |
最近记录: |