インターフェイスビルダーで、保持 Command + = テキストに合わせてボタンのサイズを変更します。ビューにボタンが追加される前に、これをプログラムで実行できるかどうか疑問に思っていました。
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button.titleLabel setFont:[UIFont fontWithName:@"Arial-BoldMT" size:12]];
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
// I need to know the width needed to accomodate NSStringVariable
[button setTitle:NSStringVariable forState:UIControlStateNormal];
// So that I can set the width property of the button before addSubview
[button setFrame:CGRectMake(10, 0, width, fixedHeight)];
[subNavigation addSubview:button];
Xcode 4.5以降では、「Auto-layouting/Constraints」を使用してこれを行うことができます。
主な利点は次のとおりです。
いくつかの欠点:
最もクールなことは、次のような意図の宣言に焦点を当てることです。
ここ は、自動レイアウトを紹介するための簡単なチュートリアルです。
詳細 の場合。
最初は少し時間がかかりますが、努力するだけの価値があるようです。
UIKitでは、特定のフォントでレンダリングされたときに取得するサイズを特定のNSStringオブジェクトから取得するために、NSStringクラスに追加されています。
ドキュメントは こちら でした。これは、非推奨の下の here です。
要するに、あなたが行く場合:
CGSize stringsize = [myString sizeWithFont:[UIFont systemFontOfSize:14]];
//or whatever font you're using
[button setFrame:CGRectMake(10,0,stringsize.width, stringsize.height)];
...ボタンのフレームを、レンダリングする文字列の高さと幅に設定します。
おそらく、そのCGSizeの周りのバッファースペースを試してみたいと思うかもしれませんが、正しい場所から始めます。
コードでこれを行う方法は次のとおりです。
[button sizeToFit];
サブクラス化していて、追加のルールを追加する場合は、オーバーライドできます。
- (CGSize)sizeThatFits:(CGSize)size;
Interface Builderでボタンを作成し、コードのタイトルを変更している場合、これを行うことができます。
[self.button setTitle:@"Button Title" forState:UIControlStateNormal];
[self.button sizeToFit];
スイフト:
ここで重要なことは、when.sizeToFit()
を呼び出します。必要なサイズを読み取ることができるようにテキストを設定した後、後でテキストを更新して再度呼び出す場合。
var button = UIButton()
button.setTitle("Length of this text determines size", forState: UIControlState.Normal)
button.sizeToFit()
self.view.addSubview(button)
自動レイアウトを使用してこれを実現するには、可変幅制約を設定してみてください。
必要な結果を得るには、Content Hugging Priority
とContent Compression Resistance Priority
を調整する必要がある場合もあります。
UILabelは、完全に自動的に自己サイズ調整されます:
このUILabelは、単純に画面の中央に設定されています(2つの制約のみ、水平/垂直)。
それは幅を完全に自動的に変更します:
any幅または高さを設定する必要はありません-それは完全に自動です。
小さな黄色の四角が単に付けられていることに注意してください(ゼロの「間隔」)。 UILabelのサイズが変更されると、それらは自動的に移動します。
「> =」制約を追加すると、UILabelの最小幅が設定されます。
ボタンではなくテキストのサイズを変更する場合は、...
button.titleLabel.adjustsFontSizeToFitWidth = YES;
button.titleLabel.minimumScaleFactor = .5;
// The .5 value means that I will let it go down to half the original font size
// before the texts gets truncated
// note, if using anything pre ios6, you would use I think
button.titleLabel.minimumFontSize = 8;
sizeToFitは正しく機能しません。代わりに:
myButton.size = myButton.sizeThatFits(CGSize.zero)
ボタンにcontentInset
を追加することもできます。
myButton.contentEdgeInsets = UIEdgeInsetsMake(8, 8, 4, 8)
単に:
UIView
をラッパーとして作成し、周囲のビューに自動レイアウトします。UILabel
を配置します。ラベルをラッパーの端に貼り付ける制約を追加します。UIButton
を配置し、UILabel
に対して行ったのと同じ制約を単純に追加します。この投稿に関連して、sizeToFit
では解決できない追加のニーズがいくつかあります。テキストに関係なく、ボタンを元の場所の中央に配置する必要がありました。また、ボタンを元のサイズよりも大きくしたくないです。
そのため、ボタンを最大サイズにレイアウトし、そのサイズをコントローラーに保存し、次の方法を使用してテキストが変更されたときにボタンのサイズを変更します。
+ (void) sizeButtonToText:(UIButton *)button availableSize:(CGSize)availableSize padding:(UIEdgeInsets)padding {
CGRect boundsForText = button.frame;
// Measures string
CGSize stringSize = [button.titleLabel.text sizeWithFont:button.titleLabel.font];
stringSize.width = MIN(stringSize.width + padding.left + padding.right, availableSize.width);
// Center's location of button
boundsForText.Origin.x += (boundsForText.size.width - stringSize.width) / 2;
boundsForText.size.width = stringSize.width;
[button setFrame:boundsForText];
}
Swift 4.2
神に感謝、これは解決しました。ボタンにテキストを設定した後、UIViewから自然なサイズであるintrinsicContentSizeを取得できます(公式ドキュメントは here です)。 UIButtonの場合、以下のように使用できます。
button.intrinsicContentSize.width
参考までに、幅を調整して適切に見えるようにしました。
button.frame = CGRect(fx: xOffset, y: 0.0, width: button.intrinsicContentSize.width + 18, height: 40)
シミュレーター
intrinsiveContentSizeを持つUIButtons
ソース: https://riptutorial.com/ios/example/16418/get-uibutton-s-size-strictly-based-on-its-text-and-font
テキストの高さの自動サイズ変更を行うこのボタンクラス(Xamarinの場合は他の言語に書き換え可能)
[Register(nameof(ResizableButton))]
public class ResizableButton : UIButton
{
NSLayoutConstraint _heightConstraint;
public bool NeedsUpdateHeightConstraint { get; private set; } = true;
public ResizableButton(){}
public ResizableButton(UIButtonType type) : base(type){}
public ResizableButton(NSCoder coder) : base(coder){}
public ResizableButton(CGRect frame) : base(frame){}
protected ResizableButton(NSObjectFlag t) : base(t){}
protected internal ResizableButton(IntPtr handle) : base(handle){}
public override void LayoutSubviews()
{
base.LayoutSubviews();
UpdateHeightConstraint();
InvalidateIntrinsicContentSize();
}
public override void SetTitle(string title, UIControlState forState)
{
NeedsUpdateHeightConstraint = true;
base.SetTitle(title, forState);
}
private void UpdateHeightConstraint()
{
if (!NeedsUpdateHeightConstraint)
return;
NeedsUpdateHeightConstraint = false;
var labelSize = TitleLabel.SizeThatFits(new CGSize(Frame.Width - TitleEdgeInsets.Left - TitleEdgeInsets.Right, float.MaxValue));
var rect = new CGRect(Frame.X, Frame.Y, Frame.Width, labelSize.Height + TitleEdgeInsets.Top + TitleEdgeInsets.Bottom);
if (_heightConstraint != null)
RemoveConstraint(_heightConstraint);
_heightConstraint = NSLayoutConstraint.Create(this, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1, rect.Height);
AddConstraint(_heightConstraint);
}
public override CGSize IntrinsicContentSize
{
get
{
var labelSize = TitleLabel.SizeThatFits(new CGSize(Frame.Width - TitleEdgeInsets.Left - TitleEdgeInsets.Right, float.MaxValue));
return new CGSize(Frame.Width, labelSize.Height + TitleEdgeInsets.Top + TitleEdgeInsets.Bottom);
}
}
}