次のようなコードがあります。
UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = @"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];
...ボタンのために複数行のテキストを持つことができるという考えですが、テキストは常にUIButtonのbackgroundImageによって隠されています。ボタンのサブビューを表示するためのロギング呼び出しは、UILabelが追加されたことを示しますが、テキスト自体は表示されません。これはUIButtonのバグですか、それとも私は何か問題がありますか?
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以降、
一般的には、次の2つのことをしてください。
選択した答えは正しいですが、Interface Builderでこのようなことをしたい場合は、次のようにします。
複数行で中央揃えされたタイトルを持つボタンを追加したい場合は、そのボタンに対するInterface Builderの設定を設定してください。
[]
IOS 6の場合:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
として
UILineBreakModeWordWrap and UITextAlignmentCenter
IOS 6以降では非推奨です。
Roger Nolanの提案をもう一度言い換えると、明示的なコードでは、これが一般的な解決策です。
button.titleLabel?.numberOfLines = 0
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center
button.setTitle("Button\nTitle",for: .normal)
IOS 7上で自動レイアウトと左寄せ:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
もっと簡単な方法があります。
someButton.lineBreakMode = UILineBreakModeWordWrap;
(iOS 3以降用に編集:)
someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
まず第一に、あなたはUIButtonがすでにその中にUILabelを持っていることを知っておくべきです。 –setTitle:forState:
を使って設定できます。
この例の問題は、UILabelのnumberOfLines
プロパティをデフォルト値の1以外に設定する必要があることです。lineBreakMode
プロパティも確認する必要があります。
ここでの答えは、マルチラインボタンのタイトルをプログラムで達成する方法を教えてくれます。
ストーリーボードを使用している場合は、[Ctrl + Enter]を押してボタンのタイトルフィールドに改行を強制することができます。
HTH
Xcode 4のストーリーボードを使用している人は、このボタンをクリックすると、右側の「属性」インスペクタの下の「ユーティリティ」パネルに、「改行」のオプションが表示されます。 「ワードラップ」を選ぶと、うまくいくはずです。
UILabelというタイトルを兄弟関係のビューにするというBrentの考えに関しては、私にとってはあまり良い考えではありません。私はタッチイベントがUIButtonの見解を通らないためにUILabelとの相互作用の問題を考え続けています。
一方、UIButtonのサブビューとしてUILabelを使用すると、タッチイベントが常に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;
}
私は時間をかけて、これについてもう少し詳しく書きました ここ 。そこでは、私はより短い解決策も指摘していますが、すべてのシナリオに完全に適合するわけではなく、いくつかの個人的な見解のハッキングを伴います。またそこでは、使用可能なUIButtonサブクラスをダウンロードすることができます。
このコードを追加する必要があります。
buttonLabel.titleLabel.numberOfLines = 0;
IOS 6で自動レイアウトを使用する場合は、preferredMaxLayoutWidth
プロパティも設定する必要があります。
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;
LineBreakModeをNSLineBreakByWordWrappingに設定すると(IBまたはコードで)、ボタンラベルは複数行になりますが、ボタンのフレームには影響しません。
ボタンに動的なタイトルがある場合、トリックが1つあります。隠しUILabelを同じフォントで配置し、その高さをボタンの高さとレイアウトで結び付けます。テキストをボタン、ラベル、自動レイアウトに設定すると、すべての作業ができます。
注
1行のボタンの本来のサイズの高さはラベルのサイズよりも大きいため、ラベルの高さが縮小するのを防ぐために、垂直方向のコンテンツハグの優先度は、ボタンの垂直方向のコンテンツ圧縮抵抗より大きくする必要があります。
自動レイアウトを使用している場合.
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2
それは完璧に機能します。
Plistのような設定ファイルでこれを使うには、CDATAを使って複数行のタイトルを書く必要があります。
<string><![CDATA[Line1
Line2]]></string>
自動レイアウトで問題が発生しました。複数行を有効にした後、結果は次のようになりました。titleLabel
のサイズはボタンのサイズに影響しませんConstraints
に基づいてcontentEdgeInsets
を追加しました(この場合、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)
])
}
}
最近では、インターフェースビルダーでケースバイケースでアクセスできるようにするためにこの種のことが本当に必要な場合は、次のような単純な拡張子でそれを実行できます。
extension UIButton {
@IBInspectable var numberOfLines: Int {
get { return titleLabel?.numberOfLines ?? 1 }
set { titleLabel?.numberOfLines = newValue }
}
}
それから、単にnumberOfLinesをラベルのように任意のUIButtonまたはUIButtonサブクラスの属性として設定できます。同じことが、ビューのレイヤーの角の半径やそれが投影する影の属性など、通常はアクセスできない他の値のホスト全体にも当てはまります。
self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
self.btnError.titleLabel?.textAlignment = .center
self.btnError.setTitle("Title", for: .normal)
Swift 5.およびXcode 10.2
SharedClass例1回書いてすべてのウェアを使う
これはあなたの共有クラスです(このようにあなたは全てのコンポーネントのプロパティを使います)
import UIKit
class SharedClass: NSObject {
static let sharedInstance = SharedClass()
private override init() {
}
}
//UIButton extension
extension UIButton {
//UIButton properties
func btnMultipleLines() {
titleLabel?.numberOfLines = 0
titleLabel?.lineBreakMode = .byWordWrapping
titleLabel?.textAlignment = .center
}
}
あなたのViewControllerでこのように呼び出します
button.btnMultipleLines()//This is your button
あなた自身のボタンクラスを転がしてください。これは、長期的にははるかに優れたソリューションです。 UIButtonや他のUIKitクラスは、カスタマイズ方法が非常に制限されています。
スイフト4.0
btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)
jessecurry's answer に STAButton を組み込みました---これは私の STAControls オープンソースライブラリの一部です。私は現在、私が開発しているアプリの1つの中でそれを使用しています、そしてそれは私の必要性のために働きます。改善方法やプルリクエストを送ってください。