स्विफ्ट में स्ट्रिंग के आधार पर यूआईबेल का आकार देखें


182

मैं अलग स्ट्रिंग की लंबाई के आधार पर एक यूबेल की ऊंचाई की गणना करने की कोशिश कर रहा हूं।

func calculateContentHeight() -> CGFloat{
    var maxLabelSize: CGSize = CGSizeMake(frame.size.width - 48, CGFloat(9999))
    var contentNSString = contentText as NSString
    var expectedLabelSize = contentNSString.boundingRectWithSize(maxLabelSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont.systemFontOfSize(16.0)], context: nil)
    print("\(expectedLabelSize)")
    return expectedLabelSize.size.height

}

ऊपर वर्तमान फ़ंक्शन है जिसका उपयोग मैं ऊंचाई निर्धारित करने के लिए करता हूं लेकिन यह काम नहीं कर रहा है। मैं किसी भी मदद की बहुत सराहना करूँगा। मैं स्विफ्ट में जवाब देना चाहता हूं और उद्देश्य सी नहीं।


डुप्लीकेट ट्राई करें इस stackoverflow.com/a/61887135/6314955
मलिथ कुरुविता

जवाबों:


517

पर एक्सटेंशन का उपयोग करें String

स्विफ्ट 3

extension String {
    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return ceil(boundingBox.height)
    }

    func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return ceil(boundingBox.width)
    }
}

और भी NSAttributedString(जो कई बार बहुत उपयोगी होता है)

extension NSAttributedString {
    func height(withConstrainedWidth width: CGFloat) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)

        return ceil(boundingBox.height)
    }

    func width(withConstrainedHeight height: CGFloat) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)

        return ceil(boundingBox.width)
    }
}

स्विफ्ट 4

बस विधियों attributesमें मान बदलेंextension String

से

[NSFontAttributeName: font]

सेवा

[.font : font]

2
@CodyWeaver चौड़ाई के लिए संपादन की जाँच करें।
करण डेडोग्लू

7
जब आप "नंबरऑफ़लाइन" = 0 का उपयोग करते हैं (जो निश्चित रूप से यूआईबेल विशिष्ट हो सकता है, तो निश्चित नहीं) या लाइनब्रेडमोड बायवॉर्डवैपिंग का उपयोग करके @KaDedeoglu यह काम कैसे करेगा। मेरा अनुमान इस तरह की विशेषताओं को जोड़ना था [NSFontAttributeName: font, NSLineBreakMode: .ByWordWrapping]लेकिन यह काम नहीं किया
Francisc0

1
मुझे लगता है कि मुझे अपना जवाब पता चल गया। मुझे NSParagraphStyleAttributeName : styleउस शैली का उपयोग करने की आवश्यकता है जहां NSMutableParagraphStyle
Francisc0

4
मुझे 'बाउंडिंग रेक्ट' के बजाय 'सेल्फबिरिंग रेक्ट' लिखना होगा अन्यथा मुझे एक कंपाइल एरर मिल जाएगी।
माइक एम।

1
इस जवाब मैं में जब इसे का उपयोग मिल गया है के साथ एक बात sizeForItemAtIndexPathएक में UICollectionViewहै कि यह करने के बदले ओवरराइड करने के लिए लगता हैinsetForSectionAt
जैक शापिरो

15

बहुस्तरीय पाठ के लिए यह उत्तर सही ढंग से काम नहीं कर रहा है। आप UILabel का उपयोग करके एक अलग स्ट्रिंग एक्सटेंशन बना सकते हैं

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

    return label.frame.height
 }
}

UILabel को एक निश्चित चौड़ाई मिलती है और .numberOfLines को 0 पर सेट किया जाता है। टेक्स्ट और कॉलिंग को जोड़कर .SizeToFit () यह स्वचालित रूप से सही ऊंचाई पर समायोजित हो जाता है।

कोड स्विफ्ट 3 ift में लिखा गया है


15
sizeToFit हालांकि ड्राइंग के कई पासों के कारण एक लाख परफॉमेंस मुद्दों का परिचय देता है। आकार को मैन्युअल रूप से गणना करना संसाधनों में सस्ता है
मार्को पैपलार्डो

2
इस समाधान को सही ऊंचाई सुनिश्चित करने के लिए यूआईबेल के यूआईएफओएनटी को निर्धारित करना चाहिए।
मैथ्यू स्पेंसर

मेरे लिए पूरी तरह से काम करता है - यहां तक ​​कि खाली तारों (स्वीकृत उत्तर के विपरीत) के लिए भी। स्वचालित ऊंचाई कोशिकाओं के साथ एक टेबल व्यू की ऊंचाई की गणना के लिए बहुत आसान है!
हेंडीज़

मैंने पाया कि स्वीकृत उत्तर एक निश्चित चौड़ाई के लिए काम करता है, लेकिन एक निश्चित ऊँचाई पर नहीं। एक निश्चित ऊंचाई के लिए, यह सिर्फ एक पंक्ति में सब कुछ फिट करने के लिए चौड़ाई बढ़ाएगा, जब तक कि पाठ में एक लाइन ब्रेक न हो। यहाँ मेरा वैकल्पिक उत्तर है: मेरा उत्तर
MSimic

2
मैंने एक समान समाधान पोस्ट किया - बिना कॉल की आवश्यकता केsizeToFit
रयान जीजी

6

Heres मेरे लिए काम करने वाला एक सरल उपाय है ... कुछ अन्य पोस्ट के समान, लेकिन इसमें कॉलिंग की आवश्यकता शामिल नहीं है sizeToFit

ध्यान दें यह स्विफ्ट 5 में लिखा गया है

let lbl = UILabel()
lbl.numberOfLines = 0
lbl.font = UIFont.systemFont(ofSize: 12) // make sure you set this correctly 
lbl.text = "My text that may or may not wrap lines..."

let width = 100.0 // the width of the view you are constraint to, keep in mind any applied margins here

let height = lbl.systemLayoutSizeFitting(CGSize(width: width, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel).height

यह लाइन रैपिंग और ऐसे हैंडल करता है। सबसे सुरुचिपूर्ण कोड नहीं है, लेकिन यह काम हो जाता है।


2
extension String{

    func widthWithConstrainedHeight(_ height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: CGFloat.greatestFiniteMagnitude, height: height)

        let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return ceil(boundingBox.width)
    }

    func heightWithConstrainedWidth(_ width: CGFloat, font: UIFont) -> CGFloat? {
        let constraintRect = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return ceil(boundingBox.height)
    }

}

1

यह स्विफ्ट 4.1 और Xcode 9.4.1 में मेरा जवाब है

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

//Function to calculate height for label based on text
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
}

अब आप इस फ़ंक्शन को कॉल करें

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

1

मैंने पाया कि स्वीकृत उत्तर एक निश्चित चौड़ाई के लिए काम करता है, लेकिन एक निश्चित ऊँचाई पर नहीं। एक निश्चित ऊंचाई के लिए, यह सिर्फ एक पंक्ति में सब कुछ फिट करने के लिए चौड़ाई बढ़ाएगा, जब तक कि पाठ में एक लाइन ब्रेक न हो।

चौड़ाई फ़ंक्शन कई बार ऊंचाई फ़ंक्शन को कॉल करता है, लेकिन यह एक त्वरित गणना है और मैंने यूआईटेबल की पंक्तियों में फ़ंक्शन का उपयोग करते हुए प्रदर्शन के मुद्दों पर ध्यान नहीं दिया।

extension String {

    public func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [.font : font], context: nil)

        return ceil(boundingBox.height)
    }

    public func width(withConstrainedHeight height: CGFloat, font: UIFont, minimumTextWrapWidth:CGFloat) -> CGFloat {

        var textWidth:CGFloat = minimumTextWrapWidth
        let incrementWidth:CGFloat = minimumTextWrapWidth * 0.1
        var textHeight:CGFloat = self.height(withConstrainedWidth: textWidth, font: font)

        //Increase width by 10% of minimumTextWrapWidth until minimum width found that makes the text fit within the specified height
        while textHeight > height {
            textWidth += incrementWidth
            textHeight = self.height(withConstrainedWidth: textWidth, font: font)
        }
        return ceil(textWidth)
    }
}

1
क्या है minimumTextWrapWidth:CGFloat?
व्याचेस्लाव गेर्चिकोव

यह फ़ंक्शन में गणना के लिए सिर्फ एक बीज मूल्य है। यदि आप चौड़ाई के बड़े होने की उम्मीद करते हैं, तो एक छोटा न्यूनतमटेक्वापड्राइफ़ चुनने से अतिरिक्त पुनरावृत्तियों से गुजरने के दौरान लूप का कारण होगा। इसलिए न्यूनतम चौड़ाई जितनी बड़ी होगी, लेकिन अगर यह आवश्यक वास्तविक चौड़ाई से बड़ी है, तो यह हमेशा वापस लौटा हुआ चौड़ाई होगी।
MSimic

0

लेबल टेक्स्ट ऊंचाई की जाँच करें और यह उस पर काम कर रहा है

let labelTextSize = ((labelDescription.text)! as NSString).boundingRect(
                with: CGSize(width: labelDescription.frame.width, height: .greatestFiniteMagnitude),
                options: .usesLineFragmentOrigin,
                attributes: [.font: labelDescription.font],
                context: nil).size
            if labelTextSize.height > labelDescription.bounds.height {
                viewMoreOrLess.hide(byHeight: false)
                viewLess.hide(byHeight: false)
            }
            else {
                viewMoreOrLess.hide(byHeight: true)
                viewLess.hide(byHeight: true)

            }

0

यह समाधान रनटाइम पर ऊंचाई और चौड़ाई की गणना करने में मदद करेगा।

    let messageText = "Your Text String"
    let size = CGSize.init(width: 250, height: 1000)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    let estimateFrame = NSString(string: messageText).boundingRect(with:  size, options: options, attributes: [NSAttributedString.Key.font: UIFont(name: "HelveticaNeue", size: 17)!], context: nil)

यहां आप अनुमानित ऊंचाई की गणना कर सकते हैं कि आपका स्ट्रिंग इसे यूआईबेल फ्रेम में ले जाएगा और पास करेगा।

estimateFrame.Width
estimateFrame.Height 

0

स्विफ्ट 5:

यदि आपके पास यूलैबेल और किसी प्रकार की बाउंडिंग रेक्ट है तो वह आपके लिए काम नहीं कर रहा है (मुझे इस समस्या का सामना करना पड़ा। यह हमेशा 1 लाइन ऊंचाई पर लौटता है।) आसानी से लेबल आकार की गणना करने के लिए एक एक्सटेंशन है।

extension UILabel {
    func getSize(constrainedWidth: CGFloat) -> CGSize {
        return systemLayoutSizeFitting(CGSize(width: constrainedWidth, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
    }
}

आप इसे इस तरह से उपयोग कर सकते हैं:

let label = UILabel()
label.text = "My text\nIs\nAwesome"
let labelSize = label.getSize(constrainedWidth:200.0)

मेरे लिये कार्य करता है


-2
@IBOutlet weak var constraintTxtV: NSLayoutConstraint!
func TextViewDynamicallyIncreaseSize() {
    let contentSize = self.txtVDetails.sizeThatFits(self.txtVDetails.bounds.size)
    let higntcons = contentSize.height
    constraintTxtV.constant = higntcons
}

5
आपके उत्तर में केवल कोड नहीं होना चाहिए, बल्कि कोड के बारे में स्पष्टीकरण भी होना चाहिए। कृपया देखें कि अधिक विवरण के लिए कैसे उत्तर दें
MechMK1

हालांकि यह कोड प्रश्न का उत्तर दे सकता है, क्यों और / या इस कोड के उत्तर के बारे में अतिरिक्त संदर्भ प्रदान करने से प्रश्न इसके दीर्घकालिक मूल्य में सुधार करता है।
इस्मा

यह उत्तर अधूरा है। यह महत्वपूर्ण चर को संदर्भित करता है जो अज्ञात हैं जो उद्देश्य को
हराते हैं
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.