iOS: UIButton ปรับขนาดตามความยาวของข้อความ


136

ในตัวสร้างอินเทอร์เฟซการกด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 A ข้อ จำกัด " มากกว่าหรือเท่ากัน " ไม่เพียงพอสำหรับความเข้ากันได้กับ AutoLayout ในปัจจุบัน (2017+) เราควรพันปุ่มไว้ในสิ่งที่ปรับขนาดได้อย่างเหมาะสม (คำตอบของBartłomiejSemańczyk) หรืออย่างใดอย่างหนึ่งควรซับคลาส UIButton เช่นเดียวกับstackoverflow.com/a/50575588/1033581
Cœur

สวัสดี @ Cœur - มีรายละเอียดปลีกย่อยมากมายในการกำหนดค่าอัตโนมัติ เป็นไปได้ว่าคุณกำลังคิดถึงสถานการณ์ที่แตกต่างออกไปเล็กน้อย? อย่างไรก็ตามโชคดีที่คุณคิดผิดทั้งหมด - ลองดู !! เพียงแค่ใส่ UIButton บนตัวควบคุมมุมมอง ตั้งศูนย์แนวนอนและแนวตั้งอย่างชัดเจน จากนั้นเพิ่มข้อ จำกัด ความกว้าง> = 100 มันทำงานได้อย่างสมบูรณ์แบบใน iOS ล่าสุด
Fattie

1
(สำหรับใครที่เพิ่งเริ่มใช้ Googleayout googling โดยอัตโนมัติที่นี่ ........... เพียงแค่ TBC คุณไม่ต้องเพิ่มอะไรเลยและ UIButton (เช่น UILabel เป็นต้น) จะปรับขนาดเป็นความกว้างโดยอัตโนมัติพร้อมกับการเปลี่ยนแปลงข้อความเพียง จำกัด ตำแหน่ง H / V ให้เหมาะสม)
Fattie

@ ฟัตตี้สาธิต . โดยเฉพาะอย่างยิ่งในขณะรันไทม์จะมีพฤติกรรมเช่นนั้น: github.com/Coeur/autolayoutButton/blob/master/buttonSelfSizing/…
Cœur

คำตอบ:


-1

ใน Xcode 4.5 ขึ้นไปตอนนี้สามารถทำได้โดยใช้ ' Auto-layouting / Constraints '

ข้อดีที่สำคัญคือ:

  1. คุณไม่จำเป็นต้องตั้งค่าเฟรมทางโปรแกรมเลย!
  2. หากทำถูกต้องคุณไม่จำเป็นต้องกังวลเกี่ยวกับการรีเซ็ตเฟรมสำหรับการเปลี่ยนแปลงการวางแนว
  3. นอกจากนี้การเปลี่ยนแปลงอุปกรณ์ไม่จำเป็นต้องรบกวนคุณ (อ่านไม่จำเป็นต้องรหัสแยกต่างหากสำหรับขนาดหน้าจอที่แตกต่างกัน)

ข้อเสียเล็กน้อย:

  1. ไม่เข้ากันได้แบบย้อนหลัง - ใช้งานได้กับ iOS 6 ขึ้นไปเท่านั้น
  2. ต้องทำความคุ้นเคย (แต่จะช่วยประหยัดเวลาในภายหลัง)

สิ่งที่เจ๋งที่สุดคือเราต้องมุ่งเน้นไปที่การประกาศเจตจำนงเช่น:

  • ฉันต้องการให้สองปุ่มนี้มีความกว้างเท่ากัน หรือ
  • ฉันต้องการให้มุมมองนี้อยู่ตรงกลางในแนวตั้งและขยายไปยังจุดสูงสุด 10 แต้มจากขอบของซุปเปอร์วิว หรือแม้กระทั่ง,
  • ฉันต้องการให้ปุ่ม / ป้ายกำกับนี้ปรับขนาดตามป้ายกำกับที่แสดง!

นี่คือบทช่วยสอนง่ายๆที่จะแนะนำเกี่ยวกับการจัดวางอัตโนมัติ

สำหรับรายละเอียดเพิ่มเติม

ต้องใช้เวลาพอสมควรในตอนแรก แต่ดูเหมือนว่าจะคุ้มค่ากับความพยายาม


3
ฉันเกือบพลาดคำตอบนี้ - มันต้องการคะแนนโหวตมากกว่านี้จริงๆ ด้วยโซลูชันนี้เราสามารถหลีกเลี่ยงการฝังชื่อและขนาดแบบอักษรหรือการโทรเฉพาะ iOS 7 ฉันเพียงแค่ตั้งค่าข้อ จำกัด ของด้านที่ฉันต้องการให้ UIButton ของฉันขยายออกไปและนั่นก็คือมัน
Carl

เกือบจะเป็นโซลูชันที่สมบูรณ์แบบ แต่น่าเสียดายที่ใช้ไม่ได้ถ้าคุณใช้ titleEdgeInsets: /
Zoltán

136
นี่เป็นคำตอบที่ไม่ดี - โดยให้รายละเอียดข้อดีของ AutoLayout เองแทนที่จะใช้ AutoLayout ในสถานการณ์นี้เพื่อแก้ปัญหาของผู้ถาม
mattsven

4
ฉันสงสัยว่านี่เป็นไปได้หรือไม่ที่จะพูดคำตอบโดยทางโปรแกรม ...
Juan Boero

@JuanPabloBoeroAlvarez ข้อ จำกัด ของเค้าโครงอัตโนมัติสามารถระบุได้ในตัวสร้างส่วนต่อประสานและ / หรือทางโปรแกรม
Slipp D.Thompson

131

ใน 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
Ben Lachman

19
sizeWithFont เลิกใช้แล้วใน iOS 7.0 ใช้ sizeWithAttributes: แทน
carmen_munich

6
ฉันขอแนะนำอย่างยิ่งว่าอย่าเล่นกับเฟรมอีกต่อไป แต่ต้องใช้ข้อ จำกัด เท่านั้น
Gil Sand

@GilSand มีวิธีใช้ตัวสร้างอินเทอร์เฟซสำหรับสิ่งนี้หรือไม่?
huggie

ใช่การค้นหาโดย Google ควรให้ผลลัพธ์ที่เป็นประโยชน์มากมาย
Gil Sand

101

วิธีทำในโค้ดคือ:

[button sizeToFit];

หากคุณเป็นคลาสย่อยและต้องการเพิ่มกฎพิเศษคุณสามารถแทนที่:

- (CGSize)sizeThatFits:(CGSize)size;

5
sizeToFit ทำงานได้อย่างสมบูรณ์แบบบนการควบคุมมาตรฐานเช่น UIButton หรือ UILabel ถ้าคุณกำลังทำมันใน UIView -(CGSize)sizeThatFits:(CGSize)sizeกำหนดเองที่คุณจะต้องดำเนินการ
Cameron Lowell Palmer

4
ใช้งานได้ก็ต่อเมื่อคุณวางไว้หลังจากตั้งค่าข้อความมิฉะนั้นจะไม่มีข้อมูลเพียงพอว่าควรจะใหญ่แค่ไหน: [button setTitle:@"Your text here" forState:UIControlStateNormal]; [button sizeToFit]; นอกจากนี้หากคุณอัปเดตข้อความในภายหลังอย่าลืมเรียกอีกครั้ง
Juan Boero

ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าข้อความด้วยวิธีนี้เท่านั้น: [myButton setTitle: @ "my title" forState: UIControlStateNormal]; สำหรับฉันมันไม่ได้ผลจนกว่าฉันจะพูดซ้ำคำพูดนั้น
Darius Miliauskas

8
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)

19

ในการทำสิ่งนี้ให้สำเร็จโดยใช้การจัดวางอัตโนมัติให้ลองตั้งค่าข้อ จำกัด ของความกว้างตัวแปร:

ข้อจำกัดความกว้าง

คุณอาจต้องปรับเปลี่ยนContent Hugging PriorityและContent Compression Resistance Priorityเพื่อให้ได้ผลลัพธ์ที่ต้องการ


UILabel ปรับขนาดเองโดยอัตโนมัติ :

UILabel นี้ถูกตั้งค่าให้อยู่กึ่งกลางบนหน้าจอ (สองข้อ จำกัด เท่านั้นแนวนอน / แนวตั้ง):

มันเปลี่ยนความกว้างโดยอัตโนมัติทั้งหมด:

คุณไม่จำเป็นต้องตั้งค่าความกว้างหรือความสูงใด ๆ - มันเป็นไปโดยอัตโนมัติทั้งหมด

ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่

สังเกตง่ายๆว่าสี่เหลี่ยมสีเหลืองเล็ก ๆ ติดอยู่ ("ระยะห่าง" ของศูนย์) พวกเขาจะย้ายโดยอัตโนมัติเมื่อปรับขนาด 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
* adjustsFontSizeToFitWidth
Daniel Bang

8

sizeToFit ทำงานไม่ถูกต้อง แทน:

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

คุณยังสามารถเพิ่มcontentInsetปุ่ม:

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


จากเอกสารของ Apple เกี่ยวกับ sizeToFit: // เรียก sizeThatFits: ด้วยขอบเขตมุมมองปัจจุบันและการเปลี่ยนแปลงขนาดขอบเขต ดังนั้นจึงทำงานได้อย่างถูกต้องคุณต้องตั้งค่าหลังจากนั้นคุณตั้งค่าข้อความ
Markus

6

สวิฟต์ 4.2

ขอบคุณพระเจ้าที่แก้ไขได้ หลังจากตั้งค่าข้อความเป็นปุ่มแล้วคุณสามารถดึงข้อมูล intrinsicContentSize ซึ่งเป็นขนาดธรรมชาติจาก UIView (เอกสารอย่างเป็นทางการอยู่ที่นี่ ) สำหรับ UIButton คุณสามารถใช้งานได้ตามด้านล่าง

button.intrinsicContentSize.width

สำหรับข้อมูลของคุณฉันได้ปรับความกว้างเพื่อให้ดูถูกต้อง

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

เครื่องจำลอง

UIButtons ที่มี intrinsicContentSize

ที่มา: 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

5

เพียงแค่:

  1. สร้าง UIViewเป็นกระดาษห่อหุ้มด้วยรูปแบบอัตโนมัติเพื่อดูรอบ ๆ
  2. ใส่ UILabelในกระดาษห่อนั้น เพิ่มข้อ จำกัด ที่จะติดฉลาก tyour ที่ขอบกระดาษห่อ
  3. ใส่UIButtonในเสื้อคลุมของคุณจากนั้นเพิ่มข้อ จำกัด เดียวกันกับที่คุณทำUILabelเช่นเดียวกับที่คุณได้สำหรับ
  4. เพลิดเพลินไปกับปุ่มปรับอัตโนมัติพร้อมกับข้อความ

1
สิ่งนี้เล่นได้ดีกับการเข้าถึงหรือไม่
jasonszhao

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];
 }

2

ด้วยเหตุผลบางอย่างfunc sizeToFit()ไม่ได้ผลสำหรับฉัน การตั้งค่าของฉันคือฉันใช้ปุ่มภายใน a UITableViewCellและฉันใช้รูปแบบอัตโนมัติ

สิ่งที่ได้ผลสำหรับฉันคือ:

  1. รับข้อ จำกัด ด้านความกว้าง
  2. ได้รับintrinsicContentSizeความกว้างเนื่องจากตามเค้าโครงอัตโนมัติของเอกสารนี้ไม่ทราบถึงไฟล์intrinsicContentSize. ตั้งค่าความกว้างเป็นintrinsicContentSizeความกว้าง

ป้อนคำอธิบายภาพที่นี่

นี่คือสองชื่อจากไฟล์ Debug View Hierachry ป้อนคำอธิบายภาพที่นี่

ป้อนคำอธิบายภาพที่นี่


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);
         }
     }
}

0

พูดตามตรงฉันคิดว่ามันน่าเสียดายจริงๆที่ไม่มีช่องทำเครื่องหมายง่ายๆในกระดานเรื่องราวที่จะบอกว่าคุณต้องการปรับขนาดปุ่มเพื่อให้เหมาะกับข้อความ อืม ...

นี่คือวิธีแก้ปัญหาที่ง่ายที่สุดโดยใช้สตอรี่บอร์ด

  1. วาง UIView และวางข้อ จำกัด ไว้ ตัวอย่าง: ป้อนคำอธิบายภาพที่นี่
  2. วาง UILabel ไว้ใน UIView กำหนดข้อ จำกัด เพื่อแนบเข้ากับขอบของ UIView

  3. วาง UIButton ของคุณไว้ใน UIView กำหนดข้อ จำกัด เดียวกันเพื่อแนบเข้ากับขอบของ UIView

  4. ตั้งค่า 0 สำหรับจำนวนบรรทัดของ UILabel ป้อนคำอธิบายภาพที่นี่

  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.