如何添加多行文本到UIButton?

我有以下代码…

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

...这个想法是,我可以有多行文本的按钮,但文本总是被UIButton的backgroundImage掩盖。显示按钮子视图的日志调用显示UILabel已添加,但文本本身无法看到。这是UIButton的bug还是我做错了什么?

204042 次浏览

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

你的例子的问题是你需要将UILabel的numberOfLines属性设置为它的默认值1以外的值。你还应该检查lineBreakMode属性。

虽然向控件添加子视图是可以的,但不能保证它会实际工作,因为控件可能不会期望它在那里,因此可能表现不佳。如果你可以摆脱它,只需添加标签作为按钮的兄弟姐妹视图,并设置它的框架,使其重叠按钮;只要它被设置为显示在按钮的顶部,按钮所做的任何事情都不会使它模糊。

换句话说:

[button.superview addSubview:myLabel];
myLabel.center = button.center;

至于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的子类。

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

有一个更简单的方法:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(适用于iOS 3及更高版本:)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

对于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. 在“换行”弹出框中选择“自动换行”

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

button.titleLabel?.numberOfLines = 0

它工作得很完美。

添加到使用这个配置文件,如Plist,你需要使用CDATA来写多行标题,像这样:

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

对于那些使用Xcode 4的故事板的人,你可以点击按钮,在右边的属性检查器下的实用工具窗格,你会看到一个换行选项。选择“换行”,应该就可以了。

对于IOS 6:

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

作为

UILineBreakModeWordWrap and UITextAlignmentCenter

在ios6以后已弃用。

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

我只是想添加,如果你正在使用故事板,你可以输入[Ctrl+Enter]强制在按钮标题字段换行。

HTH

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

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

iOS7上的自动布局左对齐:

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

选择的答案是正确的,但如果你喜欢在接口生成器中做这样的事情,你可以这样做:

pic

设置lineBreakMode为nslinebreakbywordwrapped(在IB或代码中)使按钮标签多行,但不影响按钮的帧。

如果按钮有动态标题,有一个技巧:把隐藏的UILabel与相同的字体,并把它的高度与按钮的高度与布局;当设置文本到按钮和标签和自动布局将使所有的工作。

请注意

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

如果你想添加一个带有多行居中标题的按钮,请为该按钮设置界面生成器的设置:

(< img src = " https://i.stack.imgur.com/xZaOC.png " alt = "这里" >)

如果你使用自动布局。

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

斯威夫特3

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


self.btnError.titleLabel?.textAlignment = .center


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

你必须添加以下代码:

buttonLabel.titleLabel.numberOfLines = 0;

斯威夫特4.0

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

我将jessecurry的回答合并到STAButton中,它是我的STAControls开源库的一部分。我目前正在开发的一个应用程序中使用它,它可以满足我的需求。欢迎就如何改进它或发送我拉请求开放问题。

在Xcode 9.3中,你可以像下面这样使用故事板

enter image description here

你需要设置按钮标题textAlignment到中心

button.titleLabel?.textAlignment = .center

你不需要像下面这样用新行(\n)设置标题文本,

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

简单设置标题,

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

这是结果,

enter image description here

现在,如果你真的需要在接口构建器中逐个访问这类东西,你可以用一个简单的扩展,像这样:

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

然后你可以简单地将numberolines设置为任何UIButton或UIButton子类的属性,就像它是一个标签一样。同样的道理也适用于其他一大堆通常无法访问的值,比如视图层的角半径,或者它所投射的阴影的属性。

我有一个自动布局的问题,启用多行后的结果是这样的 enter image description here < br > 因此titleLabel大小不影响按钮大小
我添加了基于contentEdgeInsetsConstraints(在本例中contenttedgeinsets为(10,10,10,10)
) 调用makeMultiLineSupport()后:
enter image description here < br > 希望它能帮助你(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)
])
}


}

斯威夫特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

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

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

要修复按钮标题标签的间距,设置titleEdgeInsets和其他属性之前 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中对齐。

添加按钮约束和子视图。这就是我如何在我的项目,让我们说它更容易这样做。我99%的时间都是通过编程来完成的。因为这对我来说容易多了。故事板有时真的会有bug [1]: https://i.stack.imgur.com/5ZSwl.png < / p >

在2021年的iOS 15中,苹果首次通过UIButton。配置 API正式支持多行uibutton。

UIButton。配置< / >

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

UIButton. < / >

这个新的API将在UIKit有什么新功能和会话中探索:

满足UIKit按钮系统

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

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

我的经验:

转到“属性”;选项卡。

短信标题,按“alt+回车”;而你想跳到下一行。

并检查“Word Wrap"属性下——>Control"字段。

picture

除了@Amir Khorsandi的回答。

你可能只需要添加uibutton.TitleLabel.TranslatesAutoresizingMaskIntoConstraints = false; 当你把它添加到uibutton本身时。(对不起,我认为你可以很容易地翻译c#)。所以uibutton.LineBreakMode = UILineBreakMode.WordWrap; 将启用多行文本。因为当你想在你的按钮中添加图像或其他东西时,这些限制会给你带来问题

基于@Amir Khorsandi的答案-但如果你有一个带有一些图像的按钮:

extension UIButton {


func enableMultiline() {
setContentHuggingPriority(.defaultLow, for: .vertical) // high hugging priority could squeeze the button to 1 line
titleLabel?.numberOfLines = 0
titleLabel?.setContentCompressionResistancePriority(.required, for: .vertical)
titleLabel?.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true
titleLabel?.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor).isActive = true
imageView?.setContentCompressionResistancePriority(.required, for: .horizontal) // otherwise image could be squeezed
}


}