iOS : 텍스트 길이에 따라 UIButton 크기 조정


134

인터페이스 빌더에서 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];

1
이 아주 오래된 질문에 주목하십시오. 요즘 (2017), 제약 조건을 "보다 크거나 같음"으로 설정하면 모든 것이 가능합니다. (Tad의 아래의 답변 답변)
Fattie

@Fattie " 보다 크거나 같은 "제약 조건은 AutoLayout과의 호환성에 충분하지 않습니다 . 요즘 (2017+) 버튼의 크기를 적절하게 조정 한 것 안에 넣거나 (Bartłomiej Semańczyk 답변) stackoverflow.com/a/50575588/1033581
Cœur

안녕하세요 @ Cœur-자동 레이아웃에는 많은 미묘한 점이 있습니다. 약간 다른 상황을 생각하고 있습니까? 그러나 다행히도, 당신은 완전히 틀 렸습니다- 그냥 시도하십시오 ! 뷰 컨트롤러에 UIButton을 넣으십시오. 분명히 수평 및 수직 중심을 설정하십시오. 그런 다음> = 100 너비 제약 조건을 추가하십시오. 최신 iOS에서 완벽하게 작동합니다.
Fattie

1
(구글링 자동 레이아웃을 처음 사용하는 사람이라면 TBC 만 있으면 아무것도 추가 할 필요가 없으며 UIButton (UILabel 등)도 텍스트 변경으로 너비가 자동으로 조정됩니다. H / V 위치를 적절하게 제한합니다.)
Fattie

@ 패티 데모 . 특히, 런타임에 다음과 같이 동작합니다 : github.com/Coeur/autolayoutButton/blob/master/buttonSelfSizing/…
Cœur

답변:


1

Xcode 4.5 이상에서는 ' 자동 레이아웃 / 제약 조건 을 사용 하여이 작업을 수행 할 수 있습니다 ' .

주요 장점은 다음과 같습니다.

  1. 프로그래밍 방식으로 프레임을 설정할 필요가 없습니다!
  2. 올바르게 수행하면 방향 변경을 위해 프레임을 재설정 할 필요가 없습니다.
  3. 또한 장치 변경에 신경 쓸 필요가 없습니다 (읽기, 다른 화면 크기에 대해 별도로 코딩 할 필요 없음).

몇 가지 단점 :

  1. 이전 버전과 호환되지 않음-iOS 6 이상에서만 작동합니다.
  2. 익숙해 져야하지만 나중에 시간을 절약 할 수 있습니다.

가장 멋진 점은 다음과 같은 의도를 선언하는 데 집중하는 것입니다.

  • 이 두 버튼의 너비가 같아야합니다. 또는
  • 이 뷰는 세로로 중앙에 위치해야하며 수퍼 뷰 가장자리에서 최대 10pt까지 확장해야합니다. 또는,
  • 이 버튼 / 레이블이 표시되는 레이블에 따라 크기를 조정하고 싶습니다!

다음 은 자동 레이아웃에 대한 간단한 자습서입니다.

자세한 내용은 .

처음에는 약간의 시간이 걸리지 만 노력할만한 가치가있는 것 같습니다.


3
나는이 답변을 거의 놓쳤다. 실제로 더 많은 투표가 필요하다. 이 솔루션을 사용하면 글꼴 이름과 크기 또는 iOS 7 전용 호출을 포함하지 않아도됩니다. UIButton을 확장하려는 측면의 제약 조건을 설정하면됩니다.
Carl

titleEdgeInsets : /
Zoltán

130
이것은 잘못된 답변입니다. AutoLayout이 어커의 문제를 해결하기 위해이 상황에서 어떻게 적용될 수 있는지보다는 AutoLayout 자체의 장점을 자세히 설명합니다.
mattsven

4
이것이 프로그래밍 적 으로 대답 할 수 있는지 궁금합니다 .
Juan Boero

@JuanPabloBoeroAlvarez 자동 레이아웃 제약 조건은 인터페이스 빌더 및 / 또는 프로그래밍 방식으로 지정할 수 있습니다.
Slipp D. Thompson

130

UIKit에는 지정된 NSString 객체에서 특정 글꼴로 렌더링 할 때 차지하는 크기를 가져 오는 NSString 클래스가 추가되었습니다.

문서가 여기에 있었습니다. 지금 여기 있습니다 추천하지 않습니다 아래.

요컨대, 당신이 가면 :

CGSize stringsize = [myString sizeWithFont:[UIFont systemFontOfSize:14]]; 
//or whatever font you're using
[button setFrame:CGRectMake(10,0,stringsize.width, stringsize.height)];

... 버튼의 프레임을 렌더링하려는 문자열의 높이와 너비로 설정했습니다.

해당 CGSize 주변의 일부 버퍼 공간을 실험하고 싶을 수도 있지만 올바른 위치에서 시작합니다.


4
iOS 기본 패딩이 12px, 8px 인 것 같습니다.
벤 Lachman

19
sizeWithFont는 iOS 7.0에서 더 이상 사용되지 않습니다. sizeWithAttributes : 대신 사용
carmen_munich

6
나는 더 이상 프레임을 가지고 놀지 말고, 대신 제약 조건 만 사용하는 것이 좋습니다.
길 샌드

@GilSand 인터페이스 빌더를 사용하는 방법이 있습니까?
huggie

예, Google 검색은 유용한 결과를 많이 제공해야합니다.
Gil Sand

101

코드에서이를 수행하는 방법은 다음과 같습니다.

[button sizeToFit];

서브 클래 싱하고 추가 규칙을 추가하려는 경우 다음을 무시할 수 있습니다.

- (CGSize)sizeThatFits:(CGSize)size;

5
sizeToFit는 UIButton 또는 UILabel과 같은 표준 컨트롤에서 완벽하게 작동합니다. 사용자 정의 UIView에서 수행하는 경우 구현해야합니다 -(CGSize)sizeThatFits:(CGSize)size.
카메론 로웰 팔머

4
텍스트를 설정 한 후 넣을 경우에만 작동합니다. 그렇지 않으면 얼마나 큰지에 대한 충분한 정보가 없습니다. [button setTitle:@"Your text here" forState:UIControlStateNormal]; [button sizeToFit]; 나중에 텍스트를 업데이트하는 경우 다시 호출하는 것을 잊지 마십시오.
Juan Boero

그런 식으로 만 텍스트를 설정해야합니다. [myButton setTitle : @ "my title"forState : UIControlStateNormal]; 저에게 그 말을 반복 할 때까지는 효과가 없었습니다.
Darius Miliauskas

7
sizeToFit()제목 가장자리 삽입을 존중하지 않습니다.
kelin

32

버튼이 Interface Builder로 작성되었고 코드에서 제목을 변경하는 경우 다음을 수행 할 수 있습니다.

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

1
버튼으로 코드를 만들었더라도 그렇게 할 수 있습니다.
Markus

22

빠른:

여기서 중요한 것은 호출 할 때 입니다 .sizeToFit(). 텍스트를 표시하도록 설정 한 후 필요한 크기를 읽을 수 있도록 표시해야합니다. 나중에 텍스트를 업데이트 한 다음 다시 호출해야합니다.

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

18

자동 레이아웃을 사용하여이 작업을 수행하려면 가변 너비 제약 조건을 설정하십시오.

폭 제약

조정 Content Hugging Priority하고 Content Compression Resistance Priority필요한 결과를 얻기 위해 필요할 수도 있습니다 .


UILabel은 완전히 자동 크기 조정됩니다 .

이 UILabel은 단순히 화면 중앙에 위치하도록 설정됩니다 (수평 / 수직의 두 가지 제약 조건 만 해당).

너비가 완전히 자동으로 변경됩니다.

당신은 설정할 필요가 없습니다 어떤 너비 또는 높이를 - 그것은 완전히 자동입니다.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

작은 노란색 사각형이 단순히 붙어 있음을 주목하십시오 ( "간격"0). UILabel의 크기가 조정되면 자동으로 이동합니다.

"> ="제약 조건을 추가하면 UILabel의 최소 너비가 설정됩니다.

여기에 이미지 설명을 입력하십시오


16

버튼이 아닌 텍스트의 크기를 조정하려면 ...

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;

3
* adjustonFontSizeToFitWidth
Daniel Bang

8

sizeToFit가 올바르게 작동하지 않습니다. 대신 :

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

contentInset버튼에 추가 할 수도 있습니다 .

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


sizeToFit에 관한 Apple 문서에서 : // sizeThatFits :를 호출하고 현재 뷰 범위와 범위 크기를 변경합니다. 따라서 올바르게 작동하면 나중에 텍스트를 설정해야합니다.
Markus

5

간단히:

  1. UIView뷰에 자동 레이아웃이있는 래퍼로 만듭니다 .
  2. 놓다 UILabel그 포장지 안에 . 라벨을 포장지 가장자리에 붙일 수있는 구속 조건을 추가하십시오.
  3. UIButton래퍼 안에 넣은 다음과 같은 제약 조건을 간단히 추가하십시오 UILabel.
  4. 텍스트와 함께 자동 크기 버튼을 즐기십시오.

1
접근성이 좋습니까?
jasonszhao

4

스위프트 4.2

신 이여 감사합니다. 텍스트를 버튼으로 설정 한 후 UIView에서 자연 크기 인 intrinsicContentSize를 검색 할 수 있습니다 (공식 문서는 여기 ). UIButton의 경우 아래와 같이 사용할 수 있습니다.

button.intrinsicContentSize.width

귀하의 정보를 위해 너비를 올바르게 조정했습니다.

button.frame = CGRect(fx: xOffset, y: 0.0, width: button.intrinsicContentSize.width + 18, height: 40)

모의 실험 장치

intrinsicContentSize를 가진 UIButtons

출처 : https://riptutorial.com/ios/example/16418/get-uibutton-s-size-strictly-based-on-its-text-and-font


1
좀 더 컨텍스트를 줄 수 있습니까? 코드 줄이 질문의 코드와 어떤 관련이 있습니까? 제안한 코드가 무엇을 요약 할 수 있습니까? 설명으로 만 링크를 제공하는 것이이 사이트에 적합한 형식은 아니지만 ( 이유 는 meta.stackexchange.com/a/8259/266197 참조 ) 설명과 컨텍스트를 추가하면 답변이 더 가치있게됩니다!
NOhs 2016 년

3

이 게시물과 관련하여 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];
 }

1

텍스트에 대한 높이 자동 크기 조정이있는이 단추 클래스 (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

어떤 이유로 든 func sizeToFit()나를 위해 작동하지 않습니다. 내 설정은 내부의 버튼을 사용하고 있으며 UITableViewCell자동 레이아웃을 사용하고 있습니다.

나를 위해 일한 것은 다음과 같습니다.

  1. 폭 제약을 얻는다
  2. intrinsicContentSize문서 에 따르면 자동 레이아웃에서를 인식하지 못 하므로 너비를 가져옵니다 intrinsicContentSize. 받는 사람 너비 제약 조건을 설정 intrinsicContentSize

여기에 이미지 설명을 입력하십시오

여기에 두 개의 제목이 있습니다 Debug View Hierachry 여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


0

솔직히 말해서 스토리 보드에는 텍스트를 수용하기 위해 버튼의 크기를 조정하고 싶다고 말하는 간단한 확인란이 없다는 것이 부끄러운 일이라고 생각합니다. 뭐 ... 뭐든지

스토리 보드를 사용하는 가장 간단한 솔루션은 다음과 같습니다.

  1. UIView를 배치하고 제약 조건을 설정하십시오. 예: 여기에 이미지 설명을 입력하십시오
  2. UILabel을 UIView 안에 넣으십시오. UIView의 가장자리에 구속 조건을 설정하십시오.

  3. UIButton을 UIView 안에 넣으십시오. 동일한 제약 조건을 설정하여 UIView의 가장자리에 연결하십시오.

  4. UILabel의 줄 수에 0을 설정하십시오. 여기에 이미지 설명을 입력하십시오

  5. 콘센트를 설정하십시오.

    @IBOutlet var button: UIButton!
    @IBOutlet var textOnTheButton: UILabel!
  1. 길고 길고 긴 제목을 얻으십시오.

    let someTitle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
  1. viewDidLoad에서 UILabel 및 UIButton에 대한 제목을 설정하십시오.

    override func viewDidLoad() {
        super.viewDidLoad()
        textOnTheButton.text = someTitle
        button.setTitle(someTitle, for: .normal)
        button.titleLabel?.numberOfLines = 0
    }
  1. 버튼 크기를 조정하고 누를 수 있도록 실행하십시오.

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.