如何向 UIButton 添加多行文本?
Posted
技术标签:
【中文标题】如何向 UIButton 添加多行文本?【英文标题】:How do you add multi-line text to a UIButton? 【发布时间】:2010-10-10 22:00:31 【问题描述】:我有以下代码...
UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = @"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];
...我的想法是我可以为按钮设置多行文本,但文本总是被 UIButton 的 backgroundImage 遮挡。显示按钮子视图的日志调用显示已添加 UILabel,但无法看到文本本身。这是 UIButton 中的错误还是我做错了什么?
【问题讨论】:
button.titleLabel?.numberOfLines = 0
注意这个非常古老的 QA,在现代 Xcode 中非常简单,选择“ATTRIBUTED TEXT” 然后很简单,选择“字符换行”。
另见updated answer 类似问题。
看到这个答案(多行,适合宽度,适合高度)按钮文本***.com/a/59211399/7523163
ios 15 现已免费提供此功能⟹ developer.apple.com/videos/play/wwdc2021/10059/?time=641 ????
【参考方案1】:
要将标题标签的间距固定到按钮,请设置 titleEdgeInsets 和其他属性 before setTitle:
let button = UIButton()
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.numberOfLines = 0
button.titleEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 20, right: 20)
button.setTitle("Dummy button with long long long long long long long long title", for: .normal)
附:我测试了设置 titleLabel?.textAlignment 不是必需的,并且标题在 .natural
中对齐。
【讨论】:
【参考方案2】:在 2021 年的 iOS 15 中,Apple 首次通过 UIButton.Configuration API 正式支持多行 UIButtons。
UIButton.Configuration
指定按钮及其内容的外观和行为的配置。
What's new in UIKit 以及会话中探索了这个新 API:
满足 UIKit 按钮系统
每个应用程序都使用按钮。在 iOS 15 中,您可以采用更新的样式来创建精美的按钮,轻松融入您的界面。我们将探索可让您更轻松地创建不同类型按钮的功能,了解如何提供更丰富的交互,并了解如何在使用 Mac Catalyst 时获得出色的按钮。
https://developer.apple.com/videos/play/wwdc2021/10064/
【讨论】:
...以及如何使用UIButtton.Configuration
实现多行功能?【参考方案3】:
添加按钮约束和子视图。这就是我在我的项目中的做法,让我们说这样更容易。我实际上 99% 的时间都以编程方式制作所有内容。因为这对我来说更容易。故事板有时真的很麻烦 [1]:https://i.stack.imgur.com/5ZSwl.png
【讨论】:
【参考方案4】:Swift 5 , UIButton 中的多行文本
let button = UIButton()
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center
button.titleLabel?.numberOfLines = 0 // for Multi line text
【讨论】:
【参考方案5】:在 Swift 5.0 和 Xcode 10.2
中//UIButton extension
extension UIButton
//UIButton properties
func btnMultipleLines()
titleLabel?.numberOfLines = 0
titleLabel?.lineBreakMode = .byWordWrapping
titleLabel?.textAlignment = .center
在您的 ViewController 调用中像这样
button.btnMultipleLines()//This is your button
【讨论】:
【参考方案6】:我遇到了自动布局的问题,启用多行后结果如下:
所以titleLabel
大小不会影响按钮大小
我基于contentEdgeInsets
添加了Constraints
(在这种情况下 contentEdgeInsets 是 (10, 10, 10, 10)
打电话后makeMultiLineSupport()
:
希望对您有所帮助(swift 5.0):
extension UIButton
func makeMultiLineSupport()
guard let titleLabel = titleLabel else
return
titleLabel.numberOfLines = 0
titleLabel.setContentHuggingPriority(.required, for: .vertical)
titleLabel.setContentHuggingPriority(.required, for: .horizontal)
addConstraints([
.init(item: titleLabel,
attribute: .top,
relatedBy: .greaterThanOrEqual,
toItem: self,
attribute: .top,
multiplier: 1.0,
constant: contentEdgeInsets.top),
.init(item: titleLabel,
attribute: .bottom,
relatedBy: .greaterThanOrEqual,
toItem: self,
attribute: .bottom,
multiplier: 1.0,
constant: contentEdgeInsets.bottom),
.init(item: titleLabel,
attribute: .left,
relatedBy: .greaterThanOrEqual,
toItem: self,
attribute: .left,
multiplier: 1.0,
constant: contentEdgeInsets.left),
.init(item: titleLabel,
attribute: .right,
relatedBy: .greaterThanOrEqual,
toItem: self,
attribute: .right,
multiplier: 1.0,
constant: contentEdgeInsets.right)
])
【讨论】:
在 swift 5 中完美运行。我还添加了我的功能以使按钮中的文本居中。 func centerTextInButton() guard let titleLabel = titleLabel else return titleLabel.textAlignment = .center 我发现没有必要添加约束,只需在设置 lineBreakMode/textAlignment/numberOfLines 后设置文本即可。并为顶部和底部插入设置 titleEdgeInsets。 @BillChan 不幸的是,这并不适用于所有情况 正如所写,这些约束每次都会导致自动布局冲突。虽然我还不能 100% 确定使用不等式约束的重要性,但我确实知道其中 2 个约束写错了:底部和右侧边缘应该使用relatedBy: .lessThanOrEqual
并翻转常量负值 constant: -contentEdgeInsets.bottom|right
跨度>
谢谢 - 由于不可见字符,我在最后一行有一个 ...
,所以我添加了 .lineBreakMode = .byClipping
【参考方案7】:
如今,如果您真的需要在界面构建器中逐个访问此类内容,您可以使用如下简单的扩展来实现:
extension UIButton
@IBInspectable var numberOfLines: Int
get return titleLabel?.numberOfLines ?? 1
set titleLabel?.numberOfLines = newValue
然后您可以简单地将 numberOfLines 设置为任何 UIButton 或 UIButton 子类的属性,就好像它是一个标签一样。其他许多通常无法访问的值也是如此,例如视图层的角半径,或者它投射的阴影的属性。
【讨论】:
【参考方案8】:在 Xcode 9.3 中,您可以使用 storyboard 来实现,如下所示,
您需要将按钮标题 textAlignment 设置为居中
button.titleLabel?.textAlignment = .center
您不需要像下面这样使用换行符 (\n) 设置标题文本,
button.setTitle("Good\nAnswer",for: .normal)
只需设置标题,
button.setTitle("Good Answer",for: .normal)
这是结果,
【讨论】:
myButton.titleLabel.textAlignment = NSTextAlignmentCenter
声明也是需要的。【参考方案9】:
我将jessecurry's answer 合并到STAButton 中,这是我的STAControls 开源库的一部分。我目前在我正在开发的一个应用程序中使用它,它可以满足我的需求。随时打开有关如何改进它的问题或向我发送拉取请求。
【讨论】:
【参考方案10】:斯威夫特 4.0
btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)
【讨论】:
【参考方案11】:您必须添加此代码:
buttonLabel.titleLabel.numberOfLines = 0;
【讨论】:
【参考方案12】:对于 iOS 6 及更高版本,使用以下命令允许多行:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
// you probably want to center it
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if you want to
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];
对于 iOS 5 及更低版本,使用以下命令允许多行:
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
// you probably want to center it
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];
2017 年,适用于 iOS9 前版,
一般来说,只需做这两件事:
-
选择“属性文本”
在“换行符”弹出窗口中选择“自动换行”
【讨论】:
请注意,这些分配在 iOS 6 中已弃用。请参阅@NiKKi 下面的答案以获取更新的语法。 让人们知道:如果您使用 NSAttributedString,这将不起作用 其实只要加上button.titleLabel.numberOfLines = 0;这将使线路无限。和 button.titleLabel.textAlignment = NSTextAlignmentLeft;如果你想要左对齐文本,因为标题默认居中。 迅速button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
感谢@Robert 的快速解决方案。也可以使用推理并省略NSLineBreakMode
,例如:button.titleLabel?.lineBreakMode = .ByWordWrapping
。【参考方案13】:
self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
self.btnError.titleLabel?.textAlignment = .center
self.btnError.setTitle("Title", for: .normal)
【讨论】:
【参考方案14】:SWIFT 3
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center
button.setTitle("Button\nTitle",for: .normal)
【讨论】:
【参考方案15】:如果您使用自动布局。
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2
【讨论】:
【参考方案16】:如果你想添加一个以多行居中的标题的按钮,请设置你的 Interface Builder 的按钮设置:
[]
【讨论】:
您能否添加有关如何实现此目的的文字说明。图片很棒,但如果它变得不可用,您的答案将毫无用处。 @RoryMcCrossan 嗨,我在上面添加了一张图片。你能看吗?请注意,Xcode 7 仍然存在问题,因此按钮标题可能会消失。但是,一旦您运行该应用程序,您将获得所需的结果。 实际上,这是该线程中的最佳答案。立即工作并显示来自 IB 的居中文本。谢谢! @user5440039 感谢您的出色回答。无需添加文字说明。【参考方案17】:将 lineBreakMode 设置为 NSLineBreakByWordWrapping(在 IB 或代码中)使按钮标签变为多行,但不影响按钮的框架。
如果按钮具有动态标题,则有一个技巧:将隐藏的 UILabel 放入相同的字体,并将其高度与布局的按钮高度绑定;当将文本设置为按钮和标签时,自动布局将完成所有工作。
注意
单行按钮的固有尺寸高度大于标签的,所以为了防止标签的高度缩小,它的垂直内容拥抱优先级必须大于按钮的垂直内容压缩阻力。
【讨论】:
【参考方案18】:重申 Roger Nolan 的建议,但使用明确的代码,这是一般解决方案:
button.titleLabel?.numberOfLines = 0
【讨论】:
大声笑,这个解决方案太完美了。谢谢!【参考方案19】:选择的答案是正确的,但如果你更喜欢在 Interface Builder 中做这种事情,你可以这样做:
【讨论】:
感谢我 24 岁的自己写下这个答案,来自 28 岁的自己。 为了保持仅使用 Interface Builder 的设置,应在User Defined Runtime Attributed
中将 titleLabel.textAlignment
和 Number
值设置为 1
以使文本居中
感谢 24 岁的自己,感谢 28 岁的自己!
感谢30岁的自己,感谢27岁的自己!【参考方案20】:
在 iOS7 上使用自动布局左对齐:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
【讨论】:
【参考方案21】:如果您在 iOS 6 上使用自动布局,您可能还需要设置 preferredMaxLayoutWidth
属性:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;
【讨论】:
【参考方案22】:这里的答案告诉你如何以编程方式实现多行按钮标题。
我只是想补充一点,如果您使用情节提要,您可以键入 [Ctrl+Enter] 以在按钮标题字段上强制换行。
HTH
【讨论】:
【参考方案23】:有一个更简单的方法:
someButton.lineBreakMode = UILineBreakModeWordWrap;
(为 iOS 3 及更高版本编辑:)
someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
【讨论】:
UIButton.lineBreakMode 在 3.0 中已被弃用,所以这不再是一个好的选择。 lineBreakMode 仅作为 UIButton 的直接属性不推荐使用。我们被定向到“改用 titleLabel 的 lineBreakMode 属性”。我相应地编辑了 Valerii 的答案。这仍然是一个不错的选择。【参考方案24】:对于 IOS 6:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
作为
UILineBreakModeWordWrap and UITextAlignmentCenter
在 IOS 6 以后已弃用..
【讨论】:
在NSText.h
的Foundation
内没有添加弃用。它从 6.0 开始可用,但未弃用。
迅速:button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
button.titleLabel?.textAlignment = NSTextAlignment.Center
【参考方案25】:
对于那些使用 Xcode 4 故事板的人,您可以单击按钮,然后在右侧的实用工具窗格中的属性检查器下,您将看到换行符选项。选择自动换行,你应该很高兴。
【讨论】:
【参考方案26】:效果很好。
添加要与Plist等配置文件一起使用,您需要使用CDATA编写多行标题,如下所示:
<string><![CDATA[Line1
Line2]]></string>
【讨论】:
【参考方案27】:滚动您自己的按钮类。从长远来看,这是迄今为止最好的解决方案。 UIButton 和其他 UIKit 类对如何自定义它们有很大的限制。
【讨论】:
【参考方案28】:至于 Brent 将标题 UILabel 作为同级视图的想法,在我看来这不是一个好主意。我一直在思考与 UILabel 的交互问题,因为它的触摸事件没有通过 UIButton 的视图。
另一方面,使用 UILabel 作为 UIButton 的子视图,我很高兴知道触摸事件将始终传播到 UILabel 的父视图。
我确实采用了这种方法,但没有注意到 backgroundImage 报告的任何问题。我在 UIButton 子类的 -titleRectForContentRect: 中添加了这段代码,但该代码也可以放在 UIButton 父视图的绘图例程中,在这种情况下,您应该将所有对 self 的引用替换为 UIButton 的变量。
#define TITLE_LABEL_TAG 1234
- (CGRect)titleRectForContentRect:(CGRect)rect
// define the desired title inset margins based on the whole rect and its padding
UIEdgeInsets padding = [self titleEdgeInsets];
CGRect titleRect = CGRectMake(rect.origin.x + padding.left,
rect.origin.x + padding.top,
rect.size.width - (padding.right + padding.left),
rect.size.height - (padding.bottom + padding].top));
// save the current title view appearance
NSString *title = [self currentTitle];
UIColor *titleColor = [self currentTitleColor];
UIColor *titleShadowColor = [self currentTitleShadowColor];
// we only want to add our custom label once; only 1st pass shall return nil
UILabel *titleLabel = (UILabel*)[self viewWithTag:TITLE_LABEL_TAG];
if (!titleLabel)
// no custom label found (1st pass), we will be creating & adding it as subview
titleLabel = [[UILabel alloc] initWithFrame:titleRect];
[titleLabel setTag:TITLE_LABEL_TAG];
// make it multi-line
[titleLabel setNumberOfLines:0];
[titleLabel setLineBreakMode:UILineBreakModeWordWrap];
// title appearance setup; be at will to modify
[titleLabel setBackgroundColor:[UIColor clearColor]];
[titleLabel setFont:[self font]];
[titleLabel setShadowOffset:CGSizeMake(0, 1)];
[titleLabel setTextAlignment:UITextAlignmentCenter];
[self addSubview:titleLabel];
[titleLabel release];
// finally, put our label in original title view's state
[titleLabel setText:title];
[titleLabel setTextColor:titleColor];
[titleLabel setShadowColor:titleShadowColor];
// and return empty rect so that the original title view is hidden
return CGRectZero;
我确实花时间写了更多关于here 的内容。在那里,我还指出了一个较短的解决方案,尽管它并不完全适合所有场景并且涉及一些私人视图黑客攻击。此外,您还可以下载一个可供使用的 UIButton 子类。
【讨论】:
【参考方案29】:虽然可以将子视图添加到控件,但不能保证它会真正起作用,因为控件可能不希望它存在,因此可能表现不佳。如果你能摆脱它,只需将标签添加为按钮的兄弟视图并设置其框架,使其与按钮重叠;只要它被设置为出现在按钮的顶部,按钮所能做的任何事情都不会掩盖它。
换句话说:
[button.superview addSubview:myLabel];
myLabel.center = button.center;
【讨论】:
拜托,如果你建议这种丑陋的方法,至少不要在你的代码示例中出错:)。如果标签是子视图,则标签不应与按钮具有相同的中心。使用 myLabel.frame = button.bounds;或 myLabel.center = cgPointMake(button.frame.size.with*0.5,button.frame.size.height*0.5) @GrizzlyNetch 我特别建议 not 将其添加为按钮的子视图。addSubview:
这里将其添加到button
的超级视图中,从而使其成为按钮的兄弟,因此匹配它们的中心是正确的。
啊,我的错!你是对的,我错过了超级视图中的“小”事实:D ...对不起:)
这不是所要求的,由于元素按钮具有标题,因此该解决方案将是实现问题的不好方法。
这在 iPhone OS 2.0 中是合理的建议。现在有很多更好的方法可以做到这一点。 :^)【参考方案30】:
首先,你应该知道 UIButton 里面已经有一个 UILabel 。您可以使用–setTitle:forState:
进行设置。
您的示例的问题是您需要将 UILabel 的 numberOfLines
属性设置为默认值 1 以外的值。您还应该查看 lineBreakMode
属性。
【讨论】:
我知道 title 属性,但据我所知,不可能将其设置为使用多行,因此采用了这种方法。如果我禁用了 backgroundImage,我的 UILabel 就会出现,这对我来说暗示了一个 bug,无论是bringSubviewToFront 还是 UIButton 本身。以上是关于如何向 UIButton 添加多行文本?的主要内容,如果未能解决你的问题,请参考以下文章