web-dev-qa-db-ja.com

iOS:テキストの長さに応じてUIButtonのサイズ変更

インターフェイスビルダーで、保持 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];
121
Oh Danny Boy

Xcode 4.5以降では、「Auto-layouting/Constraints」を使用してこれを行うことができます。

主な利点は次のとおりです。

  1. プログラムでフレームを設定する必要はまったくありません!
  2. 正しく行われていれば、向きの変更のためにフレームをリセットする必要はありません。
  3. また、デバイスの変更に煩わされる必要はありません(読み、画面サイズごとに個別にコーディングする必要はありません).

いくつかの欠点:

  1. 下位互換性なし-iOS 6以降でのみ動作します。
  2. 慣れる必要があります(ただし、後で時間を節約できます)。

最もクールなことは、次のような意図の宣言に焦点を当てることです。

  • これらの2つのボタンは同じ幅にする必要があります。または
  • このビューは、垂直方向の中央に配置し、スーパービューのエッジから最大10ポイントまで拡張する必要があります。あるいは、
  • このボタン/ラベルは、表示されているラベルに従ってサイズを変更したいです!

ここ は、自動レイアウトを紹介するための簡単なチュートリアルです。

詳細 の場合。

最初は少し時間がかかりますが、努力するだけの価値があるようです。

5
codeburn

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の周りのバッファースペースを試してみたいと思うかもしれませんが、正しい場所から始めます。

126
Dan Ray

コードでこれを行う方法は次のとおりです。

[button sizeToFit];

サブクラス化していて、追加のルールを追加する場合は、オーバーライドできます。

- (CGSize)sizeThatFits:(CGSize)size;
98
Daniel Wood

Interface Builderでボタンを作成し、コードのタイトルを変更している場合、これを行うことができます。

[self.button setTitle:@"Button Title" forState:UIControlStateNormal];
[self.button sizeToFit];
31
guptron

スイフト:

ここで重要なことは、when.sizeToFit()を呼び出します。必要なサイズを読み取ることができるようにテキストを設定した後、後でテキストを更新して再度呼び出す場合。

var button = UIButton()
button.setTitle("Length of this text determines size", forState: UIControlState.Normal)
button.sizeToFit()
self.view.addSubview(button)
19
Juan Boero

自動レイアウトを使用してこれを実現するには、可変幅制約を設定してみてください。

Width Constraint

必要な結果を得るには、Content Hugging PriorityContent Compression Resistance Priorityを調整する必要がある場合もあります。


UILabelは、完全に自動的に自己サイズ調整されます

このUILabelは、単純に画面の中央に設定されています(2つの制約のみ、水平/垂直)。

それは幅を完全に自動的に変更します:

any幅または高さを設定する必要はありません-それは完全に自動です。

enter image description here

enter image description here

小さな黄色の四角が単に付けられていることに注意してください(ゼロの「間隔」)。 UILabelのサイズが変更されると、それらは自動的に移動します。

「> =」制約を追加すると、UILabelの最小幅が設定されます。

enter image description here

16
Tad

ボタンではなくテキストのサイズを変更する場合は、...

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;
14
Logan

sizeToFitは正しく機能しません。代わりに:

myButton.size = myButton.sizeThatFits(CGSize.zero)

ボタンにcontentInsetを追加することもできます。

myButton.contentEdgeInsets = UIEdgeInsetsMake(8, 8, 4, 8)

6

単に:

  1. UIViewをラッパーとして作成し、周囲のビューに自動レイアウトします。
  2. そのラッパー内にUILabelを配置します。ラベルをラッパーの端に貼り付ける制約を追加します。
  3. ラッパー内にUIButtonを配置し、UILabelに対して行ったのと同じ制約を単純に追加します。
  4. 自動サイズのボタンとテキストをお楽しみください。

この投稿に関連して、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];
 }
3
raider33

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

1
nator333

テキストの高さの自動サイズ変更を行うこのボタンクラス(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);
         }
     }
}
1
elamaunt