ChatGPT解决这个技术问题 Extra ChatGPT

如何向 UIButton 添加多行文本?

我有以下代码...

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”,然后很简单,选择“character wrap”。
另请参阅 updated answer 的类似问题。
看到这个答案(多行,适合宽度,适合高度)按钮文本stackoverflow.com/a/59211399/7523163
iOS 15 现在免费提供此功能⟹ developer.apple.com/videos/play/wwdc2021/10059/?time=641 🥳

F
Fattie

对于 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
A
Adam Waite

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

https://i.stack.imgur.com/Qk9Bg.png


感谢我 24 岁的自己写下这个答案,来自 28 岁的自己。
并且要保持仅使用 Interface Builder 设置,应在 User Defined Runtime Attributed 中将具有 Number 值的 titleLabel.textAlignment 设置为 1 以使文本居中
感谢我24岁的自己28岁的自己!
感谢27岁的自己,感谢30岁的自己!
J
Jamal

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

https://i.stack.imgur.com/xZaOC.png


您能否添加有关如何实现此目的的文字描述。图像很棒,但如果它变得不可用,您的答案将毫无用处。
@RoryMcCrossan 嗨,我在上面添加了一张图片。你能看吗?请注意,Xcode 7 仍然存在问题,因此按钮标题可能会消失。但是,一旦您运行该应用程序,您将获得所需的结果。
实际上,这是该线程中的最佳答案。立即工作并显示来自 IB 的居中文本。谢谢!
@user5440039 感谢您的出色回答。无需添加文字说明。
N
NiKKi

对于 IOS 6:

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

作为

UILineBreakModeWordWrap and UITextAlignmentCenter

从 IOS 6 起已弃用..


Foundation 中的 NSText.h 内没有添加已弃用的内容。它从 6.0 开始可用,但未弃用。
迅速:button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping button.titleLabel?.textAlignment = NSTextAlignment.Center
m
ma11hew28

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

button.titleLabel?.numberOfLines = 0

大声笑,这个解决方案是如此完美。谢谢!
C
Community

斯威夫特 3

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

A
Amir Khorsandi

https://i.stack.imgur.com/AdaOn.png

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
N
Nazrul Islam

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

https://i.stack.imgur.com/ZRdnx.png

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

button.titleLabel?.textAlignment = .center

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

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

只需设置标题,

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

这是结果,

https://i.stack.imgur.com/U0Uly.png


myButton.titleLabel.textAlignment = NSTextAlignmentCenter 语句也是必需的。
W
Wienke

有一个更简单的方法:

someButton.lineBreakMode = UILineBreakModeWordWrap;

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

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

UIButton.lineBreakMode 在 3.0 中已被弃用,因此这不再是一个好的选择。
lineBreakMode 仅作为 UIButton 的直接属性不推荐使用。我们被定向到“改用 titleLabel 的 lineBreakMode 属性”。我相应地编辑了 Valerii 的答案。它仍然是一个不错的选择。
n
neoneye

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

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

R
Rog

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

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


我知道 title 属性,但据我所知,不可能将其设置为使用多行,因此采用这种方法。如果我禁用了 backgroundImage,我的 UILabel 就会显示出来,这对我来说暗示了一个 bug,无论是bringSubviewToFront 还是 UIButton 本身。
M
Manikandan

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

  let button = UIButton()
  button.titleLabel?.lineBreakMode = .byWordWrapping
  button.titleLabel?.textAlignment = .center
  button.titleLabel?.numberOfLines = 0 // for Multi line text

G
Guntis Treulands

要将标题标签的间距固定到按钮,请在 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 中对齐。


J
Jack

对于那些使用 Xcode 4 的故事板的人,您可以单击按钮,然后在右侧的实用程序窗格中的属性检查器下,您将看到换行符选项。选择自动换行,你应该很高兴。


u
user2338871

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

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

高温高压


V
Varrry

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

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

笔记

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


J
JimHawkins

您必须添加以下代码:

buttonLabel.titleLabel.numberOfLines = 0;

j
jpedroso

至于 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;
}

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


v
vially

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

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;

A
Ash

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

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

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


N
Naresh

在 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

m
makiko_fly

它完美地工作。

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

<string><![CDATA[Line1
Line2]]></string>

S
Sourabh Sharma

如果您使用自动布局。

button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2

i
ingconti

迅捷4.0

btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)

佚名

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


p
pkamb

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

UIButton.Configuration 一种配置,用于指定按钮及其内容的外观和行为。

https://i.stack.imgur.com/KW92R.png

这个新的 API 在 What's new in UIKit 以及会话中进行了探索:

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


...以及如何使用 UIButtton.Configuration 实现多行功能?
B
Bugs
self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping

self.btnError.titleLabel?.textAlignment = .center

self.btnError.setTitle("Title", for: .normal)

S
Stunner

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


M
Milosh Milivojevich

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


B
Becca Royal-Gordon

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

换句话说:

[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 中是合理的建议。现在有很多更好的方法可以做到这一点。 :^)