ปรับความสูงของ UILabel เป็นข้อความ


112

ฉันมีป้ายกำกับบางป้ายที่ฉันต้องการปรับความสูงให้เป็นข้อความนี่คือรหัสที่ฉันเขียนไว้ตอนนี้

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height
}

แก้ไข:

ปัญหาไม่ได้อยู่ในโค้ดส่วนนี้ดังนั้นการแก้ไขของฉันจึงอยู่ในคำถามนั้นเอง มันอาจยังมีประโยชน์สำหรับคนอื่น ๆ !


ดูการเพิ่มเติม NSString UIKit มีวิธีการคำนวณขนาดตามที่คุณต้องการโดยไม่ต้องสร้าง UILabel
Vladimir Gritsenko

@VladimirGritsenko วิธีการ 'sizeWithFont' ไม่สามารถใช้ได้ใน Swift :(
TheBurgerShot

ฉันยอมรับว่าฉันไม่ใช่ผู้เชี่ยวชาญด้าน Swift แต่ฉันเชื่อว่าคุณสามารถเพิ่มวิธีการเชื่อมโยงของคุณเองได้ ยังคงคุ้มค่ากว่าการสร้าง UILabel เพื่อคำนวณขนาด
Vladimir Gritsenko

@TheBurgerShot sizeWithFontอาจไม่มีให้ใช้กับ Swift Stringแต่มีให้ใช้งานNSStringคุณควรจะยังสามารถเรียกใช้งานได้
Anorak

ในท้ายที่สุดข้อผิดพลาดก็แตกต่างออกไปและไม่มีส่วนเกี่ยวข้องกับวิธีนี้ แม้ว่าสิ่งนี้อาจเป็นประโยชน์สำหรับคนอื่น ๆ
TheBurgerShot

คำตอบ:


189

ฉันเพิ่งใส่สิ่งนี้ในสนามเด็กเล่นและมันก็เหมาะกับฉัน

อัปเดตสำหรับ Swift 4.0

import UIKit

 func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height
}

let font = UIFont(name: "Helvetica", size: 20.0)

var height = heightForView("This is just a load of text", font: font, width: 100.0)

Swift 3:

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()

    return label.frame.height
}

ใส่คำอธิบายภาพที่นี่


มันใช้งานได้ดีสำหรับฉันเช่นกันในสนามเด็กเล่นข้อผิดพลาดดูเหมือนจะไม่เกิดขึ้นในสถานที่เฉพาะนี้เมื่อฉันลบการใช้งานของวิธีนี้มันจะสะอื้นเกี่ยวกับ println บางส่วนหรือเพียงแค่บรรทัดที่มีความคิดเห็นเท่านั้น (จากนั้นระบุว่ารหัส EXC_BAD_ACCESS = 2 ด้วย)
TheBurgerShot

6
ทำงานในสนามเด็กเล่น แต่ไม่มีการปรับขนาดตามที่ต้องการภายในตัวควบคุมมุมมองใน XCode 6.1
Unome

1
ฉันลังเลเล็กน้อยที่จะสร้างใหม่UILabelต่อขนาด หากใช้วิธีนี้ภายในlayoutSubviewsโดยมีแนวโน้มที่จะเรียกใช้หลายครั้งต่อรูปแบบที่สมบูรณ์การสร้างวัตถุพิเศษอาจทำให้เกิดความล่าช้าที่เห็นได้ชัดเจนโดยเฉพาะอย่างยิ่งในระหว่างการเลื่อน
Zorayr

ให้ textRect = textString.boundingRectWithSize (CGSizeMake (320, 2000), ตัวเลือก: .UsesLineFragmentOrigin, แอตทริบิวต์: textAttributes, บริบท: nil)
Siddharth Pancholi

ฉันไม่สามารถเรียกใช้ฟังก์ชันนี้ในตัวควบคุมมุมมองของฉัน ... คุณช่วยแนะนำฉันได้ไหมว่าอะไรเป็นสาเหตุที่เป็นไปได้
Rouny

64

หากคุณใช้ AutoLayoutคุณสามารถปรับUILabelความสูงได้โดยกำหนดค่า UI เท่านั้น

สำหรับ iOS8 ขึ้นไป

  • กำหนดข้อ จำกัด นำหน้า / ต่อท้ายสำหรับไฟล์ UILabel
  • และเปลี่ยนบรรทัดUILabelจาก 1 เป็น 0

ใส่คำอธิบายภาพที่นี่

สำหรับ iOS7.2

  • ขั้นแรกคุณต้องเพิ่มความสูงสำหรับUILabel
  • จากนั้นแก้ไขความสัมพันธ์จากEqualเป็นGreater than or Equal

ใส่คำอธิบายภาพที่นี่

  • สุดท้ายเปลี่ยนบรรทัดUILabelจาก 1 เป็น 0

ใส่คำอธิบายภาพที่นี่

ของคุณUILabelจะเพิ่มความสูงโดยอัตโนมัติขึ้นอยู่กับข้อความ


2
และถ้าฉลากอยู่ภายในเซลล์ คุณจะเพิ่มความสูงของเซลล์เมื่อใดและอย่างไร
oyalhi

1
@oyalhi ถ้าป้ายของคุณอยู่ในเซลล์ tableview โปรดดูโพสต์อื่น ๆ ของฉันstackoverflow.com/a/36277840/5381331
Phan Van Linh

3
สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน! ตั้งค่าข้อ จำกัด และจะทำงานได้อย่างถูกต้อง!
Bill Thompson

2
ไม่ได้ผลสำหรับฉัน ... คำว่า "Label" ใน UILabel ทำให้ height = 20 จะยังคงเป็น 20 หลังจากการตั้งค่านี้
gadget00

9

ฉันสร้างส่วนขยายนี้หากคุณต้องการ

extension UILabel {
    func setSizeFont (sizeFont: CGFloat) {
        self.font =  UIFont(name: self.font.fontName, size: sizeFont)!
        self.sizeToFit()
    }
}

8

ฉันมีโซลูชันการทำงานที่แข็งแกร่ง

ในรูปแบบ

    _title.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 0)
    _title.sizeToFit()
    _title.frame.size = _title.bounds.size

ในตัวตั้งค่าข้อความ:

    _title.text = newValue
    setNeedsLayout()

UPD. แน่นอนด้วยการตั้งค่า UILabel นี้:

    _title.lineBreakMode = .ByWordWrapping
    _title.numberOfLines = 0

6

เพียงแค่ตั้งค่า:

label.numberOfLines = 0

ป้ายกำกับจะปรับความสูงโดยอัตโนมัติตามจำนวนข้อความที่ป้อน


27
สิ่งนี้ไม่ได้ทำให้ UILabel ปรับความสูงได้
TheBurgerShot

6

จากคำตอบของ Anorak ฉันเห็นด้วยกับข้อกังวลของ Zorayr ดังนั้นฉันจึงเพิ่มบรรทัดสองสามบรรทัดเพื่อลบ UILabel และส่งคืนเฉพาะ CGFloat ฉันไม่รู้ว่ามันช่วยได้หรือไม่เนื่องจากรหัสเดิมไม่ได้เพิ่ม UIabel แต่มัน ไม่เกิดข้อผิดพลาดดังนั้นฉันจึงใช้รหัสด้านล่าง:

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{

    var currHeight:CGFloat!

    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()

    currHeight = label.frame.height
    label.removeFromSuperview()

    return currHeight
}

5

ใน Swift 4.1 และ Xcode 9.4.1

เพียง3 ขั้นตอน

ขั้นตอนที่ 1)

//To calculate height for label based on text size and width
func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat {
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height
}

ขั้นตอนที่ 2)

//Call this function
let height = heightForView(text: "This is your text", font: UIFont.systemFont(ofSize: 17), width: 300)
print(height)//Output : 41.0

ขั้นตอนที่ 3)

//This is your label
let proNameLbl = UILabel(frame: CGRect(x: 0, y: 20, width: 300, height: height))
proNameLbl.text = "This is your text"
proNameLbl.font = UIFont.systemFont(ofSize: 17)
proNameLbl.numberOfLines = 0
proNameLbl.lineBreakMode = .byWordWrapping
infoView.addSubview(proNameLbl)

5

โซลูชันที่ Anorak แนะนำเป็นคุณสมบัติที่คำนวณได้ในส่วนขยายสำหรับ UILabel:

extension UILabel
{
var optimalHeight : CGFloat
    {
        get
        {
            let label = UILabel(frame: CGRectMake(0, 0, self.frame.width, CGFloat.max))
            label.numberOfLines = 0
            label.lineBreakMode = self.lineBreakMode
            label.font = self.font
            label.text = self.text

            label.sizeToFit()

            return label.frame.height
         }
    }
}

การใช้งาน:

self.brandModelLabel.frame.size.height = self.brandModelLabel.optimalHeight

ทางออกที่ดี! ขอบคุณ :-)
Cristina

ไม่สามารถกำหนดให้กับคุณสมบัติ: 'height' เป็นคุณสมบัติรับอย่างเดียว
Amg91

4

ตามด้วยคำตอบของ @Anorak ฉันได้เพิ่มส่วนขยายนี้ลงใน String และส่งสิ่งที่ใส่เข้าไปเป็นพารามิเตอร์เนื่องจากหลายครั้งคุณจะต้องมีช่องว่างในข้อความของคุณ อย่างไรก็ตามบางทีคุณอาจพบว่าสิ่งนี้มีประโยชน์

extension String {

    func heightForWithFont(font: UIFont, width: CGFloat, insets: UIEdgeInsets) -> CGFloat {

        let label:UILabel = UILabel(frame: CGRectMake(0, 0, width + insets.left + insets.right, CGFloat.max))
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.ByWordWrapping
        label.font = font
        label.text = self

        label.sizeToFit()
        return label.frame.height + insets.top + insets.bottom
    }
}

label.lineBreakMode = NSLineBreakMode ByWordWrapping บรรทัดนี้ช่วยฉันด้วยขอบคุณ
Coder_A_D

3

นี่คือวิธีคำนวณความสูงของข้อความใน Swift จากนั้นคุณสามารถรับความสูงจาก rect และตั้งค่าความสูงของป้ายกำกับหรือ textView เป็นต้น

let font = UIFont(name: "HelveticaNeue", size: 25)!
let text = "This is some really long text just to test how it works for calculating heights in swift of string sizes. What if I add a couple lines of text?"

let textString = text as NSString

let textAttributes = [NSFontAttributeName: font]

let textRect = textString.boundingRectWithSize(CGSizeMake(320, 2000), options: .UsesLineFragmentOrigin, attributes: textAttributes, context: nil)

3

เพียงเรียกวิธีนี้เมื่อคุณต้องการความสูงแบบไดนามิกสำหรับป้ายกำกับ

func getHeightforController(view: AnyObject) -> CGFloat {
    let tempView: UILabel = view as! UILabel
    var context: NSStringDrawingContext = NSStringDrawingContext()
    context.minimumScaleFactor = 0.8

    var width: CGFloat = tempView.frame.size.width

    width = ((UIScreen.mainScreen().bounds.width)/320)*width

    let size: CGSize = tempView.text!.boundingRectWithSize(CGSizeMake(width, 2000), options:NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: tempView.font], context: context).size as CGSize

    return size.height
}

3

Swift 4.0

self.messageLabel = UILabel (เฟรม: CGRect (x: 70, y: 60, ความกว้าง: UIScreen.main.bounds.width - 80, สูง: 30)

messageLabel.text = message

messageLabel.lineBreakMode = .byWordWrapping //in versions below swift 3 (messageLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping)    
messageLabel.numberOfLines = 0 //To write any number of lines within a label scope

messageLabel.textAlignment = .center

messageLabel.textColor = UIColor.white

messageLabel.font = messageLabel.font.withSize(12)

messageLabel.sizeToFit()

Blockquote NSParagraphStyle.LineBreakMode ใช้กับทั้งย่อหน้าไม่ใช่คำภายในย่อหน้าคุณสมบัตินี้จะมีผลทั้งในระหว่างการวาดปกติและในกรณีที่ต้องลดขนาดฟอนต์เพื่อให้พอดีกับข้อความของป้ายกำกับในกรอบขอบเขต คุณสมบัตินี้ถูกตั้งค่าเป็น byTruncatingTail ตามค่าเริ่มต้น

ลิงก์นี้อธิบายถึงวิธีการทำสตอรีบอร์ดในลักษณะเดียวกัน


2
คำตอบแบบใช้รหัสเท่านั้นไม่ถือเป็นแนวทางปฏิบัติที่ดี โปรดพิจารณาเพิ่มคำอธิบายว่าคำตอบของคุณตอบคำถามอย่างไร
Yannis

2

Swift 4.0

แทนที่จะคำนวณความสูงของข้อความ / ฉลากฉันแค่ปรับขนาดป้ายกำกับหลังจากแทรกข้อความ (ไดนามิก)

สมมติว่า myLabel เป็น UILabel ที่เป็นปัญหา:

let myLabel = UILabel(frame: CGRect(x: 0, y: 0, width: *somewidth*, height: *placeholder, e.g. 20*))
myLabel.numberOfLines = 0
myLabel.lineBreakMode = .byWordWrapping
...

และตอนนี้ก็มาถึงส่วนที่สนุก:

var myLabelText: String = "" {
   didSet {
      myLabel.text = myLabelText
      myLabel.sizeToFit()
   }
}

2

Swift 4.1วิธีขยายความสูงฉลากคำนวณ:

extension UILabel {

    func heightForLabel(text:String, font:UIFont, width:CGFloat) -> CGFloat {
        let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
        label.font = font
        label.text = text

        label.sizeToFit()
        return label.frame.height
    }

}

1

ทางสตอรี่บอร์ดของ Swift 5, XCode 11 ฉันคิดว่ามันใช้ได้กับ iOS 9 ขึ้นไป คุณต้องการตัวอย่างเช่นป้ายกำกับ "คำอธิบาย" เพื่อรับความสูงแบบไดนามิกให้ทำตามขั้นตอน:

1) เลือกป้ายกำกับคำอธิบาย -> ไปที่ Attributes Inspector (ไอคอนดินสอ), ตั้งค่า: Lines: 0 Line Break: Word Wrap

2) เลือก UILabel ของคุณจากสตอรี่บอร์ดและไปที่ Size Inspector (ไอคอนไม้บรรทัด) 3) ไปที่ "ลำดับความสำคัญของการต้านทานการบีบอัดเนื้อหาเป็น 1 สำหรับองค์ประกอบ UIView อื่น ๆ ทั้งหมด (ป้ายกำกับปุ่มมุมมองภาพ ฯลฯ ) ที่โต้ตอบกับป้ายกำกับของคุณ

ตัวอย่างเช่นฉันมี UIImageView, Title Label และ Description Label ในแนวตั้งในมุมมองของฉัน ฉันตั้งค่าลำดับความสำคัญความต้านทานการบีบอัดเนื้อหาเป็น UIImageView และป้ายชื่อเป็น 1 และสำหรับป้ายกำกับคำอธิบายเป็น 750 สิ่งนี้จะทำให้ป้ายคำอธิบายรับความสูงได้มากตามต้องการ


0

หากต้องการสร้างป้ายกำกับแบบไดนามิกอย่างรวดเร็วอย่ากำหนดค่าความสูงและในสตอรีบอร์ดให้จำนวนบรรทัดเป็น 0 ให้ข้อ จำกัด ด้านล่างด้วยและนี่เป็นวิธีที่ดีที่สุดในการจัดการป้ายกำกับแบบไดนามิกตามขนาดเนื้อหา


0

คุณยังสามารถใช้sizeThatFitsฟังก์ชัน

ตัวอย่างเช่น:

label.sizeThatFits(superView.frame.size).height

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.