386

我有以下代码...

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

...我的想法是我可以为按钮设置多行文本,但文本总是被 UIButton 的 backgroundImage 遮挡。显示按钮子视图的日志调用显示已添加 UILabel,但无法看到文本本身。这是 UIButton 中的错误还是我做错了什么?

4

30 回答 30

699

对于 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 前进

通常,只需执行以下两件事:

  1. 选择“属性文本”
  2. 在“换行符”弹出窗口中选择“自动换行”
于 2009-12-01T22:34:56.043 回答
153

选择的答案是正确的,但如果您更喜欢在 Interface Builder 中执行此类操作,您可以执行以下操作:

图片

于 2014-05-14T15:36:05.383 回答
61

如果要添加标题居中的多行按钮,请设置 Interface Builder 的按钮设置:

[ 这里]

于 2015-10-21T09:03:53.627 回答
54

对于 IOS 6:

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

作为

UILineBreakModeWordWrap and UITextAlignmentCenter

从 IOS 6 起已弃用..

于 2012-10-08T07:14:08.883 回答
32

重申 Roger Nolan 的建议,但使用明确的代码,这是一般解决方案:

button.titleLabel?.numberOfLines = 0
于 2010-10-28T15:45:02.900 回答
22

斯威夫特 3

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center  
button.setTitle("Button\nTitle",for: .normal)
于 2017-05-08T09:56:36.190 回答
17

我遇到了自动布局的问题,启用多行后结果是这样的: 所以大小不会影响 我添加的按钮大小(在这种情况下 contentEdgeInsets 是 (10, 10, 10, 10 ) 致电后: 希望对您有所帮助(swift 5.0):
在此处输入图像描述
titleLabel
ConstraintscontentEdgeInsets
makeMultiLineSupport()
在此处输入图像描述

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)
            ])
    }

}
于 2019-04-11T21:25:00.460 回答
15

在 Xcode 9.3 中,您可以使用下面的情节提要来做到这一点,

在此处输入图像描述

您需要将按钮标题 textAlignment 设置为居中

button.titleLabel?.textAlignment = .center

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

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

只需设置标题,

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

这是结果,

在此处输入图像描述

于 2018-05-31T06:14:28.007 回答
11

有一个更简单的方法:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(针对 iOS 3 及更高版本进行编辑:)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
于 2009-10-25T19:48:31.960 回答
11

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

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
于 2013-06-28T19:07:50.057 回答
7

首先,你应该知道 UIButton 里面已经有一个 UILabel 。您可以使用–setTitle:forState:.

您的示例的问题是您需要将 UILabel 的numberOfLines属性设置为默认值 1 以外的其他值。您还应该查看该lineBreakMode属性。

于 2009-03-03T08:35:36.170 回答
5

Swift 5,用于 UIButton 中的多行文本

  let button = UIButton()
  button.titleLabel?.lineBreakMode = .byWordWrapping
  button.titleLabel?.textAlignment = .center
  button.titleLabel?.numberOfLines = 0 // for Multi line text
于 2019-11-22T09:45:52.907 回答
4

对于那些使用 Xcode 4 的故事板的人,您可以单击该按钮,然后在 Attributes Inspector 下的右侧 Utilities 窗格中,您将看到 Line Break 的选项。选择自动换行,你应该很高兴。

于 2012-05-09T18:12:27.617 回答
4

这里的答案告诉你如何以编程方式实现多行按钮标题。

我只是想补充一点,如果您使用情节提要,您可以键入 [Ctrl+Enter] 以在按钮标题字段上强制换行。

高温高压

于 2013-05-01T09:50:09.847 回答
4

将 lineBreakMode 设置为 NSLineBreakByWordWrapping(在 IB 或代码中)使按钮标签变为多行,但不影响按钮的框架。

如果按钮具有动态标题,则有一个技巧:将隐藏的 UILabel 放入相同的字体并将其高度与布局的按钮高度联系起来;当将文本设置为按钮和标签时​​,自动布局将完成所有工作。

笔记

单行按钮的固有尺寸高度大于标签的,所以为了防止标签的高度收缩,它的垂直内容拥抱优先级必须大于按钮的垂直内容压缩阻力。

于 2015-08-31T20:21:44.733 回答
4

您必须添加以下代码:

buttonLabel.titleLabel.numberOfLines = 0;
于 2018-02-21T11:41:43.403 回答
3

至于 Brent 将标题 UILabel 作为同级视图的想法,在我看来这不是一个好主意。我一直在思考与 UILabel 的交互问题,因为它的触摸事件没有通过 UIButton 的视图。

另一方面,使用 UILabel 作为 UIButton 的子视图,我很高兴知道触摸事件将始终传播到 UILabel 的超级视图。

我确实采用了这种方法,并没有注意到 backgroundImage 报告的任何问题。我在 UIButton 子类的 -titleRectForContentRect: 中添加了这段代码,但代码也可以放在 UIButton 父视图的绘图例程中,在这种情况下,您应该用 UIButton 的变量替换所有对 self 的引用。

#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;
}

我确实花时间在这里写了更多关于此的内容。在那里,我还指出了一个较短的解决方案,尽管它并不完全适合所有场景并且涉及一些私人视图黑客攻击。此外,您还可以下载一个可供使用的 UIButton 子类。

于 2009-03-09T14:25:47.963 回答
3

如果您在 iOS 6 上使用自动布局,您可能还需要设置preferredMaxLayoutWidth属性:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;
于 2013-05-01T18:45:41.753 回答
3

如今,如果您真的需要在界面构建器中逐个访问这种东西,您可以使用如下简单的扩展来实现:

extension UIButton {
    @IBInspectable var numberOfLines: Int {
        get { return titleLabel?.numberOfLines ?? 1 }
        set { titleLabel?.numberOfLines = newValue }
    }
}

然后,您可以简单地将 numberOfLines 设置为任何 UIButton 或 UIButton 子类的属性,就好像它是一个标签一样。对于其他许多通常无法访问的值也是如此,例如视图层的角半径,或者它投射的阴影的属性。

于 2018-11-17T07:12:59.827 回答
3

Swift 5.0Xcode 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
于 2019-04-29T04:54:53.240 回答
3

要将标题标签的间距固定到按钮,请在 setTitle之前设置 titleEdgeInsets 和其他属性:

    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)

PS 我测试了设置 titleLabel?.textAlignment 不是必需的,并且标题在.natural.

于 2020-03-04T18:28:33.783 回答
2

它完美地工作。

添加与 Plist 等配置文件一起使用,您需要使用 CDATA 编写多行标题,如下所示:

<string><![CDATA[Line1
Line2]]></string>
于 2011-05-11T10:04:58.020 回答
2

如果您使用自动布局。

button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2
于 2016-12-09T10:55:27.320 回答
2

迅捷4.0

btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)
于 2018-03-25T12:50:04.153 回答
1

滚动你自己的按钮类。从长远来看,这是迄今为止最好的解决方案。UIButton 和其他 UIKit 类在如何自定义它们方面非常严格。

于 2009-03-10T13:16:10.243 回答
1

在 2021 年的 iOS 15 中,Apple 首次通过UIButton.Configuration API 正式支持多行 UIButtons。

UIButton.Configuration

指定按钮及其内容的外观和行为的配置。

UIButton.Configuration

这个新的 API在 UIKit 中的新功能以及会话中进行了探索:

满足 UIKit 按钮系统

每个应用程序都使用按钮。在 iOS 15 中,您可以采用更新的样式来创建精美的按钮,轻松融入您的界面。我们将探索可以更轻松地创建不同类型按钮的功能,了解如何提供更丰富的交互,并了解如何在使用 Mac Catalyst 时获得出色的按钮。

https://developer.apple.com/videos/play/wwdc2021/10064/

于 2021-06-08T15:34:17.103 回答
0
self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping

self.btnError.titleLabel?.textAlignment = .center

self.btnError.setTitle("Title", for: .normal)
于 2017-08-03T09:40:40.380 回答
0

我在STAButton中合并了jessecurry 的答案,这是我的STAControls开源库的一部分。我目前在我正在开发的一个应用程序中使用它,它可以满足我的需求。随意打开有关如何改进它的问题或向我发送拉取请求。

于 2018-05-05T23:27:21.537 回答
0

添加按钮约束和子视图。这就是我在我的项目中的做法,让我们说这样更容易。我实际上 99% 的时间都以编程方式制作所有内容。因为这对我来说更容易。情节提要有时可能会出现问题 [1]:https ://i.stack.imgur.com/5ZSwl.png

于 2020-08-09T20:18:34.563 回答
-4

尽管可以将子视图添加到控件中,但不能保证它会真正起作用,因为控件可能不希望它在那里,因此可能表现不佳。如果你能摆脱它,只需将标签添加为按钮的兄弟视图并设置其框架,使其与按钮重叠;只要它被设置为出现在按钮的顶部,按钮就无法做任何事情来掩盖它。

换句话说:

[button.superview addSubview:myLabel];
myLabel.center = button.center;
于 2009-03-03T12:04:43.500 回答