如何在UIButton上添加多行文本?

391

我有下面这段代码...

UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = @"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];

我想实现按钮的多行文本,但按钮的backgroundImage始终遮挡文本。调用日志显示该UIButton的子视图中已添加了UILabel,但文本本身无法显示。这是UIButton的错误还是我的操作有误?


10
该代码的作用是设置按钮标题文本的行数为0,以便自动调整文本大小以适应按钮的大小。其中titleLabel是按钮的标题标签,?.表示如果此属性不为nil,则执行后面的代码,否则跳过该语句。 - ma11hew28
2
请注意,对于这个非常古老的 QA,在现代 Xcode 中非常简单,只需选择“属性文本”,然后就很容易了,选择“字符换行”。 - Fattie
还可以参考类似问题的更新答案 - ToolmakerSteve
请查看此答案(多行,适合宽度,适合高度)以获取按钮文本 https://dev59.com/l1wY5IYBdhLWcg3wgH3y#59211399 - Hamid Reza Ansari
iOS 15现在免费提供此功能 ⟹ https://developer.apple.com/videos/play/wwdc2021/10059/?time=641 - XLE_22
33个回答

700

对于 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];

从iOS9开始,一般来说只需做这两件事:

  1. 选择"Attributed Text"(富文本)
  2. "Line Break"(换行)弹出窗口中选择"Word Wrap"(自动换行)

5
请注意,这些任务在iOS 6中已被弃用。请查看@NiKKi下面的答案以获取更新的语法。 - Aaron Brager
6
提醒大家:如果你正在使用NSAttributedString,这种方法是行不通的。 - The dude
31
只需添加 button.titleLabel.numberOfLines = 0; 即可使行数无限制。如果您想要左对齐的文本,可以添加 button.titleLabel.textAlignment = NSTextAlignmentLeft; 因为标题默认是居中对齐的。 - RyJ
4
在 Swift 中,button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping 的意思是将按钮的标题文字按单词换行。 - Robert
2
请注意,如果您想使用AutoLayout,UIButton存在一个错误,会导致内在内容大小与边缘插图无法正常工作。为了解决这个问题,请参考https://dev59.com/9GMm5IYBdhLWcg3wMssp,其中提供了一个很好的解决方案。 - DrMickeyLauer
显示剩余4条评论

158

所选答案是正确的,但如果您更喜欢在 Interface Builder 中进行此类操作,则可以按照以下步骤:

图片


94
感谢我24岁的自己写下这篇回答,此时的我已经28岁了。 - Adam Waite
5
为了保持使用 Interface Builder 的设置,可以在“用户定义的运行时属性”中将titleLabel.textAlignment的“数字”值设置为1,以使文本居中显示。 - AnthoPak
3
感谢你,28岁的自己,来自24岁的我! - user5306470
谢谢你,30岁的自己,来自27岁的我! - Mr. Disability

61
如果您想添加一个标题居中且有多行的按钮,请设置按钮的Interface Builder设置:

[此处]


你能否添加一个文字描述来说明如何实现这个功能。图片固然好,但如果它不可用,你的回答就毫无意义了。 - Rory McCrossan
1
@RoryMcCrossan 你好,我在上面添加了一张图片。你能看到吗?请注意,Xcode 7仍然存在一些错误,因此按钮标题可能会消失。但是,一旦你运行应用程序,你将得到期望的结果。 - user5440039
2
这实际上是这个帖子中最好的答案。立即起作用并显示来自IB的居中文本。谢谢! - RainCast
@user5440039,感谢您提供的出色答案。无需添加文本描述。 - Fattie

54

针对iOS 6:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;

As

UILineBreakModeWordWrap and UITextAlignmentCenter

从IOS 6开始,已经不建议使用它们了。


Foundation 中的 NSText.h 文件中没有添加任何已弃用的内容。它从6.0版本开始就可用,但并未被弃用。 - Alex Cio
在 Swift 中:button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrappingbutton.titleLabel?.textAlignment = NSTextAlignment.Center - jcity

32

为了重申Roger Nolan的建议,但带着明确的代码,这是通用解决方案:

button.titleLabel?.numberOfLines = 0

哈哈,这个解决方案太完美了。谢谢! - PhillipJacobs

23

SWIFT 3

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center  
button.setTitle("Button\nTitle",for: .normal)

21

我在使用自动布局时遇到了问题,启用多行后结果如下:
enter image description here
所以titleLabel的大小没有影响按钮的大小。
我根据contentEdgeInsets(在这种情况下是 (10, 10, 10, 10))添加了Constraints
调用makeMultiLineSupport()后:
enter image description here
希望对你有所帮助(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} - ShadeToD
我发现添加约束并不是必要的,只需在设置lineBreakMode/textAlignment/numberOfLines之后设置文本即可。还要为顶部和底部插图设置titleEdgeInsets。 - Bill Chan
@BillChan 很遗憾,这并不适用于所有情况。 - Amir Khorsandi
2
如此编写,这些约束每次都会导致自动布局冲突。虽然我还没有完全确定使用不等式约束的重要性,但我知道其中2个约束写错了:底部和右侧边缘应该使用 relatedBy: .lessThanOrEqual 并翻转常量负数 constant: -contentEdgeInsets.{bottom|right} - androidguy
谢谢 - 我在最后一行有一个 ... 由于一个不可见的字符,所以我已经添加了 .lineBreakMode = .byClipping - user2330482

15

在Xcode 9.3中,您可以通过使用下面的故事板来完成这个操作,

enter image description here

您需要将按钮标题文本对齐方式设置为居中。

button.titleLabel?.textAlignment = .center

您不需要像下面这样使用换行符(\n)来设置标题文本,

button.setTitle("Good\nAnswer",for: .normal)

只需设置标题即可,

button.setTitle("Good Answer",for: .normal)

这是结果,

enter image description here


还需要包括 myButton.titleLabel.textAlignment = NSTextAlignmentCenter 这条语句。 - tounaobun

11

有更简单的方法:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(编辑iOS 3及更高版本:)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

4
UIButton.lineBreakMode在3.0版本中已经被弃用,因此不再是一个好的选择。 - Christopher Pickslay
2
lineBreakMode已经过时,只能作为UIButton的直接属性。我们被指示“改用titleLabel的lineBreakMode属性”。我相应地编辑了Valerii的答案。它仍然是一个不错的选择。 - Wienke

11

使用自动布局在 iOS7 上左对齐:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接