NSAttributedString गलत आकार वापस करने के लिए बाध्य करें


151

मैं एक जिम्मेदार स्ट्रिंग के लिए रूट प्राप्त करने की कोशिश कर रहा हूं, लेकिन बाउंडिंग रेक्टविटसाइज कॉल मैं जिस आकार से गुजरता हूं उसका सम्मान नहीं कर रहा हूं और एक बड़ी ऊंचाई (यह एक लंबी स्ट्रिंग है) के विपरीत एक सिंगल लाइन ऊंचाई के साथ एक रूट वापस कर रहा है। मैंने ऊंचाई के लिए एक बहुत बड़े मूल्य में पास करके प्रयोग किया है और नीचे दिए गए कोड के अनुसार 0 भी है, लेकिन जो रिटर्न दिया गया है वह हमेशा समान है।

CGRect paragraphRect = [attributedText boundingRectWithSize:CGSizeMake(300,0.0)
  options:NSStringDrawingUsesDeviceMetrics
  context:nil];

क्या यह टूट गया है, या क्या मुझे कुछ और करने की ज़रूरत है, क्योंकि यह लिपटे पाठ के लिए एक परत वापस कर सकता है?


5
क्या आप ट्रंकिंग / क्लिपिंग के साथ एक पैराग्राफ शैली है lineBreakMode?
danyowdee 19

1
यदि आप इसे पढ़ रहे हैं, क्योंकि UILabel मापने / गलत चौड़ाई से लपेटने पर stackoverflow.com/questions/46200027/… पर एक नज़र डालते हैं । विशेष रूप से, NSAllowsDefaultLineBreakStrategy को ऐप लॉन्च पर गलत तरीके से सेट करना।
एरिक

जवाबों:


312

लगता है कि आप सही विकल्प प्रदान नहीं कर रहे थे। रैपिंग लेबलों के लिए, कम से कम प्रदान करें:

CGRect paragraphRect =
  [attributedText boundingRectWithSize:CGSizeMake(300.f, CGFLOAT_MAX)
  options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
  context:nil];

नोट: यदि मूल पाठ की चौड़ाई 300 से कम है, तो लाइन रैपिंग नहीं होगी, इसलिए सुनिश्चित करें कि बाध्य आकार सही है, अन्यथा आपको अभी भी गलत परिणाम मिलेंगे।


25
सभी को इस उत्तर को देखने की जरूरत है, क्योंकि यह काम करता है। शायद इस विधि के लिए स्पष्ट प्रलेखन की आवश्यकता होती है और सामान्य रूप से तार को जिम्मेदार ठहराया जाता है; यह स्पष्ट नहीं है कि आपको कहाँ देखना है।
मैकसर्व

31
ध्यान! यह हमेशा काम नहीं करता है! कभी-कभी लौटा हुआ चौड़ाई आकार पैरामीटर की चौड़ाई से बड़ा होता है। यहां तक ​​कि सेब विधि प्रलेखन में कहा गया है: "आकार पैरामीटर में आपके द्वारा निर्दिष्ट बाधाएं स्ट्रिंग को आकार देने के लिए रेंडरर के लिए एक मार्गदर्शिका हैं। हालांकि, इस विधि द्वारा लौटाए गए वास्तविक बाउंडिंग आयत अतिरिक्त जगह की आवश्यकता होने पर बाधाओं से बड़ा हो सकता है। पूरे स्ट्रिंग को प्रस्तुत करें। "
काल

75
NSAttributedString और boundingRectWithSize के लिए एपीआई बिल्कुल चौंकाने वाला है।
6

27
एक और गोचा है कि पैराग्राफ में लौटाए गए ऊंचाई (और संभवतः चौड़ाई) लगभग हमेशा एक आंशिक मूल्य है। तो यह 141.3 ऊंचाई कहकर निकल सकता है। आपको परिणाम का उपयोग करने की आवश्यकता है ceilf(paragraphRect.size.height)ताकि यह गोल हो जाए। मैं हर समय यह भूल जाता हूं और आश्चर्य करता हूं कि मेरे लेबल अभी भी क्यों चिपके हुए हैं।
जाम

39
मैं हमेशा boundingRectWithSize:CGRectIntegral () में अपनी गणना को लपेटता हूं CGRectIntegral rounds the rectangle’s origin downward and its size upward to the nearest whole integers, जो इस मामले में ऊँचाई और चौड़ाई को गोल करता है ताकि यह सुनिश्चित हो सके कि ऊँचाई या चौड़ाई एक भिन्नात्मक मूल्य नहीं है।
भागदौड़

47

किसी कारण से, बाउंडिंग रेक्टविटसाइज़ हमेशा गलत आकार देता है। मुझे एक उपाय सूझा। UItextView -sizeThatFits के लिए एक विधि है जो पाठ सेट के लिए उचित आकार देता है। इसलिए बाउंडिंगRectWithSize का उपयोग करने के बजाय, एक यादृच्छिक फ्रेम के साथ एक UITextView बनाएं, और संबंधित चौड़ाई और CGFLOAT_MAX ऊंचाई के साथ इसके आकार को कॉल करें। यह उस आकार को वापस करता है जिसमें उचित ऊँचाई होगी।

   UITextView *view=[[UITextView alloc] initWithFrame:CGRectMake(0, 0, width, 10)];   
   view.text=text;
   CGSize size=[view sizeThatFits:CGSizeMake(width, CGFLOAT_MAX)];
   height=size.height; 

यदि आप थोड़ी देर के लूप में आकार की गणना कर रहे हैं, तो यह जोड़ना न भूलें कि एक ऑटोरिलिज़ पूल में, क्योंकि इसमें यूआईटैक्स्यूव्यू की संख्या n बनाई जाएगी, अगर हम ऑटोरेल्टरपूल का उपयोग नहीं करते हैं तो ऐप की रन टाइम मेमोरी बढ़ जाएगी।


1
यह काम। मैंने जिन अन्य तरीकों की कोशिश की, मैं कभी काम नहीं कर पाया। मुझे लगता है कि मेरी समस्या जिम्मेदार स्ट्रिंग की जटिलता से उपजी है जिसे मैं असाइन कर रहा था। यह एक RTF फ़ाइल से आ रहा था और इसमें कई प्रकार के फोंट, लाइन रिक्ति, यहां तक ​​कि छाया का उपयोग किया गया था, और UseLineFragmentOrigin और UseFontLeading का उपयोग करने के बावजूद मैं कभी भी ऐसा परिणाम नहीं प्राप्त कर सका जो पर्याप्त रूप से लंबा था, और समस्या सबसे खराब थी लंबे समय तक जिम्मेदार स्ट्रिंग। मेरा अनुमान है कि अपेक्षाकृत सरल तार के लिए बाउंडिंग रेक्टविथसाइज़ विधि काम कर सकती है । उन्हें वास्तव में इसके साथ काम करने के बेहतर तरीके की जरूरत है, इमो।
जॉन बुशनेल

क्या आपको नहीं लगता कि विधि के UITextViewरूप में heightForRowAtIndexPathकहा जाता है के रूप में कई बार बनाने के लिए यह overkill है ? यह समय लगता है
जेनोस

मैं आपसे @ János सहमत हूं, लेकिन यह एकमात्र समाधान था जिसने मेरे लिए काम किया।
शॉन

btw मैंने उचित समाधान के लिए कहा: stackoverflow.com/questions/32495744/…
János

यह एकमात्र उपाय है जो काम करता है। इस समस्या के 9 साल हैं और Apple जाहिरा तौर पर इसे हल नहीं करना चाहता है या इसके इंजीनियर इसके समाधान का पता लगाने के लिए कमजोर हैं। हम यहां iOS 11 के बारे में बात कर रहे हैं, अभी भी वही बग ले जा रहा है।
डक

31

एड मैकमैनस ने निश्चित रूप से इसे काम करने के लिए एक कुंजी प्रदान की है। मुझे एक ऐसा मामला मिला जो काम नहीं करता है

UIFont *font = ...
UIColor *color = ...
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                     font, NSFontAttributeName,
                                     color, NSForegroundColorAttributeName,
                                     nil];

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString: someString attributes:attributesDictionary];

[string appendAttributedString: [[NSAttributedString alloc] initWithString: anotherString];

CGRect rect = [string boundingRectWithSize:constraint options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil];

रेक्ट की सही ऊंचाई नहीं होगी। सूचना है कि anotherString (जो में जोड़ा जाता है स्ट्रिंग ) एक विशेषता शब्दकोश के बिना प्रारंभ किया गया था। यह एक और स्ट्रींग के लिए एक वैध इनिशियलाइज़र है, लेकिन बाउंडिंग रेक्टविथसाइज़ : इस मामले में सटीक आकार नहीं देता है।


33
धन्यवाद! पता चलता है कि एक NSAttributedString के हर हिस्से में कम से कम NSFontAttributeName और NSForegroundColorAttributeName सेट के साथ एक शब्दकोश सेट होना चाहिए, यदि आप वास्तव में काम करना चाहते हैं! मुझे वह दस्तावेज कहीं दिखाई नहीं देता।
बेन व्हीलर

3
ध्यान दें कि यह भी प्रतीत होता है कि अलग-अलग NSAttributedStrings, जो एक एकल बनाने के लिए संयुक्त हैं, सभी को SAME शब्दकोश (और इस प्रकार एक ही फ़ॉन्ट) का उपयोग करना चाहिए ताकि वह सही ढंग से काम करने के लिए बाध्य हो सके!
बेन व्हीलर

1
यह समाधान मेरे यूआईबेल श्रेणी के लिए "सिकुड़कर फिट होने" के लिए उपयोग करने के समान है। मेरे लिए इसे काम पर लाने की कुंजी FLT_MAX ऊंचाई के साथ बाउंडिंग आयत बनाना था। इसके बिना, मुझे सिर्फ एक पंक्ति के लिए एक आयत प्रतीत होगी।
dre1138

+ 1s सभी दौर में। यह वास्तव में मुझे मिला, इसलिए इसे बाहर काम करने के लिए धन्यवाद दोस्तों।
वीएक्स

मुझे यह समस्या थी। मैंने NSMutableAttributedStringबिना विशेषताओं के रिक्त स्थान और न्यूलाइन्स का उपयोग किया और मुझे गलत आकार मिल रहा था।
वबजनर

28

लंबी जांच के बाद मेरा अंतिम निर्णय:
- boundingRectWithSizeकेवल पात्रों के निर्बाध अनुक्रम के लिए फ़ंक्शन सही आकार देता है! मामले में स्ट्रिंग में रिक्त स्थान या कुछ और होता है (जिसे ऐप्पल द्वारा कहा जाता है "ग्लिफ़ के कुछ") - पाठ प्रदर्शित करने के लिए आवश्यक वास्तविक आकार की परत प्राप्त करना असंभव है!
मैंने पत्रों द्वारा अपने तार में जगह बदल दी है और तुरंत सही परिणाम मिला है।

Apple यहां कहता है: https://developer.apple.com/documentation/foundation/nsstring/1524729-boundingrectwithsize

"यह विधि स्ट्रिंग में ग्लिफ़ की वास्तविक सीमा लौटाती है। कुछ ग्लिफ़ (रिक्त स्थान, उदाहरण के लिए) में दिए गए आकार द्वारा निर्दिष्ट लेआउट अवरोधों को ओवरलैप करने की अनुमति होती है, इसलिए कुछ मामलों में आकार के घटक की चौड़ाई का मान लौटा CGRectआकार पैरामीटर की चौड़ाई मान से अधिक हो सकता है। "

इसलिए वास्तविक आय की गणना के लिए कुछ और तरीका खोजना आवश्यक है ...


लंबी जांच प्रक्रिया के बाद आखिरकार समाधान मिल गया !!! मुझे यकीन नहीं है कि इससे संबंधित सभी मामलों के लिए अच्छा काम होगा UITextView, लेकिन मुख्य और महत्वपूर्ण बात का पता चला था!

boundingRectWithSizeफ़ंक्शन और साथ ही CTFramesetterSuggestFrameSizeWithConstraints(और कई अन्य तरीके) सही आयत का उपयोग करते समय आकार और पाठ भाग की सही गणना करेंगे। उदाहरण के लिए - UITextViewहै textView.bounds.size.width- और यह मान वास्तविक आयत नहीं है जिसका उपयोग सिस्टम द्वारा पाठ ड्राइंग पर किया जाता है UITextView

मुझे बहुत दिलचस्प पैरामीटर मिला और कोड में सरल गणना का प्रदर्शन किया:

CGFloat padding = textView.textContainer.lineFragmentPadding;  
CGFloat  actualPageWidth = textView.bounds.size.width - padding * 2;

और जादू काम करता है - मेरे सभी ग्रंथों की गणना अभी! का आनंद लें!


1
हाँ, मैंने देखा कि यह भी चौड़ाई के लिए बाधा नहीं रखता है, यह हमेशा बड़ा होता है। यह वास्तव में अच्छा नहीं है, उन्होंने काम करने की विधि को हटा दिया और अब हमें इस बकवास से निपटना होगा।
बोरिस गाफरोव

1
आप सर, मेरे नए हीरो हैं! यह मुझे पागल कर रहा था। मैं textContainers insets सेट कर रहा हूं, इसलिए textView.bounds.size.witdh के बजाय textView.textContainer.size. उपलब्धता का उपयोग करना था।
GCBenson

मैं इसे पर्याप्त वोट नहीं दे सका। इतना अजीब कि अंतरिक्ष की गणना को बाध्य नहीं किया जाता है।
हॉलैंड

1
"3" जैसे कुछ डमी चरित्र के साथ रिक्त स्थान की जगह सटीक ऊंचाई देता है
अबुजर अमीन

1
इसने मेरे कैरियर और क्यूए टीम के साथ मेरे संबंधों को बचाया। मैं तुम्हें एक बियर आदमी देना !!
lucaslt89

14

स्विफ्ट चार संस्करण

let string = "A great test string."
let font = UIFont.systemFont(ofSize: 14)
let attributes: [NSAttributedStringKey: Any] = [.font: font]
let attributedString = NSAttributedString(string: string, attributes: attributes)
let largestSize = CGSize(width: bounds.width, height: .greatestFiniteMagnitude)

//Option one (best option)
let framesetter = CTFramesetterCreateWithAttributedString(attributedString)
let textSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRange(), nil, largestSize, nil)

//Option two
let textSize = (string as NSString).boundingRect(with: largestSize, options: [.usesLineFragmentOrigin , .usesFontLeading], attributes: attributes, context: nil).size

//Option three
let textSize = attributedString.boundingRect(with: largestSize, options: [.usesLineFragmentOrigin , .usesFontLeading], context: nil).size

CTFramesetter के साथ पाठ को मापना सबसे अच्छा काम करता है क्योंकि यह पूर्णांक आकार प्रदान करता है और इमोजी और अन्य यूनिक वर्णों को अच्छी तरह से संभालता है।


10

मुझे इनमें से किसी भी सुझाव के साथ भाग्य नहीं मिला। मेरी स्ट्रिंग में यूनिकोड बुलेट बिंदु थे और मुझे संदेह है कि वे गणना में दुःख पैदा कर रहे थे। मैंने देखा कि UITextView ड्राइंग ठीक कर रहा था, इसलिए मैंने इसकी गणना का लाभ उठाने के लिए देखा। मैंने निम्नलिखित कार्य किया, जो संभवतः एनएसएसट्रिंग ड्राइंग विधियों के रूप में इष्टतम नहीं है, लेकिन कम से कम यह सटीक है। यह सिर्फ कॉल करने के लिए एक UITextView को शुरू करने की तुलना में थोड़ा अधिक इष्टतम है -sizeThatFits:

NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(width, CGFLOAT_MAX)];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[layoutManager addTextContainer:textContainer];

NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:formattedString];
[textStorage addLayoutManager:layoutManager];

const CGFloat formattedStringHeight = ceilf([layoutManager usedRectForTextContainer:textContainer].size.height);

यह यूनिकोड डॉट्स नहीं हो सकता है, यह आपके स्ट्रिंग के अंत में रिक्त स्थान हो सकता है। : उपरोक्त जवाब देखें stackoverflow.com/a/25941139/337934
सामब

9

यदि आप पूंछ को काटकर बाउंडिंग बॉक्स प्राप्त करना चाहते हैं, तो यह प्रश्न आपकी मदद कर सकता है।

CGFloat maxTitleWidth = 200;

NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = NSLineBreakByTruncatingTail;

NSDictionary *attributes = @{NSFontAttributeName : self.textLabel.font,
                             NSParagraphStyleAttributeName: paragraph};

CGRect box = [self.textLabel.text
              boundingRectWithSize:CGSizeMake(maxTitleWidth, CGFLOAT_MAX)
              options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
              attributes:attributes context:nil];

9

यह बताता है कि NSAttributedString के किसी भी भाग में कम से कम NSFontAttributeName और NSForegroundColorAttributeName सेट के साथ एक शब्दकोश सेट होना चाहिए, यदि आप बाउंडिंग करना चाहते हैं तो वास्तव में काम करने की पुष्टि करें!

मुझे वह दस्तावेज कहीं दिखाई नहीं देता।


धन्यवाद, यह मेरे लिए समाधान था, सिवाय मैंने पाया कि केवल NSFontAttributeName आवश्यक था, न कि NSForegroundColorAttributeName
Marmoy

7

@warrenm यह कहने के लिए क्षमा करें कि फ्रेमसेट्टर विधि मेरे लिए कारगर नहीं थी।

मुझे यह मिल गया। यह फ़ंक्शन हमें दिए गए चौड़ाई के लिए iphone / Ipad SDK में एक NSAttributedString की एक स्ट्रिंग रेंज के लिए आवश्यक फ्रेम आकार को निर्धारित करने में मदद कर सकता है:

इसका उपयोग UITableView Cells की गतिशील ऊंचाई के लिए किया जा सकता है

- (CGSize)frameSizeForAttributedString:(NSAttributedString *)attributedString
{
    CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);
    CGFloat width = YOUR_FIXED_WIDTH;

    CFIndex offset = 0, length;
    CGFloat y = 0;
    do {
        length = CTTypesetterSuggestLineBreak(typesetter, offset, width);
        CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(offset, length));

        CGFloat ascent, descent, leading;
        CTLineGetTypographicBounds(line, &ascent, &descent, &leading);

        CFRelease(line);

        offset += length;
        y += ascent + descent + leading;
    } while (offset < [attributedString length]);

    CFRelease(typesetter);

    return CGSizeMake(width, ceil(y));
}

HADDAD ISSA >>> http://haddadissa.blogspot.in/2010/09/compute-needed-heigh-for-fixed-width-of.html के लिए धन्यवाद


मेरे लिए किसी भी डिवाइस (iPhone 4 और 5) पर काम नहीं करता है। दोनों iOS7.1.2 के साथ डिवाइस और iOS8.3 के साथ 4s सिम्युलेटर :(
sanjana

यह किसी भी आयात की जरूरत है?
jose920405

@ कर्णअलैंगट हां#import <CoreText/CoreText.h>
jose920405

7

मैंने पाया है कि पसंदीदा समाधान लाइन ब्रेक को नहीं संभालता है।

मैंने पाया है कि यह दृष्टिकोण सभी मामलों में काम करता है:

UILabel* dummyLabel = [UILabel new];
[dummyLabel setFrame:CGRectMake(0, 0, desiredWidth, CGFLOAT_MAX)];
dummyLabel.numberOfLines = 0;
[dummyLabel setLineBreakMode:NSLineBreakByWordWrapping];
dummyLabel.attributedText = myString;
[dummyLabel sizeToFit];
CGSize requiredSize = dummyLabel.frame.size;

मेरे मामले में मुझे बैकग्राउंड थ्रेड पर गणना करनी चाहिए, और यूआई तत्वों के उपयोग की अनुमति नहीं है
लब्बू

4

मुझे इन तकनीकों का उपयोग करके एक सटीक आकार नहीं मिलने के साथ एक ही समस्या हुई है और मैंने इसे काम करने के लिए अपना दृष्टिकोण बदल दिया है।

मेरे पास एक लंबे समय से जिम्मेदार स्ट्रिंग है जिसे मैं एक स्क्रॉल दृश्य में फिट करने की कोशिश कर रहा हूं ताकि यह बिना छंटनी किए ठीक से दिखाई दे। पाठ के काम को मज़बूती से करने के लिए मैंने जो किया वह एक बाधा के रूप में ऊँचाई को बिल्कुल भी निर्धारित नहीं करना था और इसके बजाय आंतरिक आकार को लेने की अनुमति दी। अब पाठ सही ढंग से काटे बिना प्रदर्शित किया जाता है और मुझे ऊंचाई की गणना करने की आवश्यकता नहीं है।

मुझे लगता है कि अगर मुझे ऊंचाई प्राप्त करने की आवश्यकता थी तो मैं मज़बूती से एक ऐसा दृश्य बनाऊंगा जो छिपा हुआ है और इन बाधाओं को लागू होने के बाद फ्रेम की ऊंचाई प्राप्त होगी।


2
क्या आप इसे प्रदर्शित करने के लिए एक कोड नमूना जोड़ सकते हैं? धन्यवाद।
नाथन बुगिया

3

Im खेल के लिए थोड़ा देर से - लेकिन मैं एक तरह से यह पता लगाने की कोशिश कर रहा हूं कि बाउंडिंग बॉक्स को खोजने के लिए काम करता है जो कि एक फ़ोकस रिंग बनाने के लिए एक जिम्मेदार स्ट्रिंग के चारों ओर फिट होगा जैसे फाइंडर में एक फ़ाइल को संपादित करना। जब मैंने स्ट्रिंग के अंत में रिक्त स्थान या स्ट्रिंग के अंदर कई रिक्त स्थान होते हैं, तो मैंने कोशिश की थी। boundingRectWithSizeइसके लिए बुरी तरह से विफल रहता है CTFramesetterCreateWithAttributedString

NSLayoutManagerनिम्नलिखित कोड का उपयोग करने से मुझे अब तक मिले सभी मामलों में चाल प्रतीत होती है और एक ऐसी परत वापस आती है जो पूरी तरह से स्ट्रिंग को बांध देती है। बोनस: यदि आप पाठ का चयन करते हैं तो चयन के किनारों पर वापस आयी हुई सीमा की सीमा तक जाती है। नीचे दिए गए कोड से एक से लेआउट प्रबंधक का उपयोग किया जाता है NSTextView

NSLayoutManager* layout = [self layoutManager];
NSTextContainer* container = [self textContainer];

CGRect focusRingFrame = [layout boundingRectForGlyphRange:NSMakeRange(0, [[self textStorage] length]) inTextContainer:container];

2
textView.textContainerInset = UIEdgeInsetsZero;
NSString *string = @"Some string";
NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:12.0f], NSForegroundColorAttributeName:[UIColor blackColor]};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:string attributes:attributes];
[textView setAttributedText:attributedString];
CGRect textViewFrame = [textView.attributedText boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.view.frame)-8.0f, 9999.0f) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil];
NSLog(@"%f", ceilf(textViewFrame.size.height));

सभी फोंट पर पूरी तरह से काम करता है!


1

मुझे भी यही समस्या थी, लेकिन मैंने माना कि ऊंचाई की कमी को सही ढंग से निर्धारित किया गया है। इसलिए मैंने निम्नलिखित कार्य किया:

-(CGSize)MaxHeighForTextInRow:(NSString *)RowText width:(float)UITextviewWidth {

    CGSize constrainedSize = CGSizeMake(UITextviewWidth, CGFLOAT_MAX);

    NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                          [UIFont fontWithName:@"HelveticaNeue" size:11.0], NSFontAttributeName,
                                          nil];

    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:RowText attributes:attributesDictionary];

    CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];

    if (requiredHeight.size.width > UITextviewWidth) {
        requiredHeight = CGRectMake(0, 0, UITextviewWidth, requiredHeight.size.height);
    }

    return requiredHeight.size;
}

1
    NSDictionary *stringAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [UIFont systemFontOfSize:18], NSFontAttributeName,
                                      [UIColor blackColor], NSForegroundColorAttributeName,
                                      nil];

    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:myLabel.text attributes:stringAttributes];
    myLabel.attributedText = attributedString; //this is the key!

    CGSize maximumLabelSize = CGSizeMake (screenRect.size.width - 40, CGFLOAT_MAX);

    CGRect newRect = [myLabel.text boundingRectWithSize:maximumLabelSize
                                                       options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                    attributes:stringAttributes context:nil];

    self.myLabelHeightConstraint.constant = ceilf(newRect.size.height);

मैंने इस पेज पर सब कुछ करने की कोशिश की और अभी भी एक यूआईबेल के लिए एक मामला था जो सही ढंग से प्रारूपित नहीं कर रहा था। वास्तव में लेबल पर एट्रिब्यूट टेक्स्ट सेट करना आखिरकार समस्या को निर्धारित करता है।


1

एक बात जो मैं नोटिस कर रहा था, वह यह है कि जो रूट से वापस आएगा (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context, उसमें मेरे द्वारा पारित होने की तुलना में एक बड़ी चौड़ाई होगी। जब ऐसा हुआ तो मेरा तार काट दिया जाएगा। मैंने इसे इस तरह हल किया:

NSString *aLongString = ...
NSInteger width = //some width;            
UIFont *font = //your font;
CGRect rect = [aLongString boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
                                        options:(NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin)
                                     attributes:@{ NSFontAttributeName : font,
                                                   NSForegroundColorAttributeName : [UIColor whiteColor]}
                                        context:nil];

if(rect.size.width > width)
{
    return rect.size.height + font.lineHeight;
}
return rect.size.height;

कुछ और संदर्भ के लिए; मेरे पास मल्टी लाइन टेक्स्ट था और मैं इसे प्रदर्शित करने के लिए सही ऊँचाई खोजने की कोशिश कर रहा था। बाउंड्रीविटसाइज़ कभी-कभी मेरी निर्दिष्ट की गई चौड़ाई से अधिक चौड़ाई वापस कर रहा था, इस प्रकार जब मैंने अपने पाठ को प्रदर्शित करने के लिए चौड़ाई और गणना की गई ऊँचाई में अपने अतीत का उपयोग किया, तो कम हो जाएगा। परीक्षण से जब बाउंडिंग रेक्टविटसाइज ने गलत चौड़ाई का उपयोग किया तो यह राशि 1 पंक्ति से कम हो जाएगी। इसलिए मैं जांच करूंगा कि क्या चौड़ाई अधिक थी और यदि ऐसा है तो फ़ॉन्ट की लाइनहाइट जोड़ें ताकि ट्रंकेशन से बचने के लिए पर्याप्त स्थान प्रदान किया जा सके।


चौड़ाई के साथ लाइन की ऊंचाई कैसे प्रभावित होती है?
रूई मुलिया

@RoiMulia लाइन की ऊँचाई चौड़ाई को प्रभावित नहीं करती है। मैंने अपने जवाब को अपडेट किया कि कैसे यह मेरी बग तय करता है।

0
    NSAttributedString *attributedText =[[[NSAttributedString alloc]
                                          initWithString:joyMeComment.content
                                          attributes:@{ NSFontAttributeName: [UIFont systemFontOfSize:TextFont]}] autorelease];

    CGRect paragraphRect =
    [attributedText boundingRectWithSize:CGSizeMake(kWith, CGFLOAT_MAX)
                                 options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                 context:nil];
    contentSize = paragraphRect.size;

    contentSize.size.height+=10;
    label.frame=contentSize;

यदि लेबल का फ्रेम 10 नहीं जोड़ता है तो यह विधि कभी काम नहीं करेगी! आशा है इससे आपको सहायता मिलेगी! खुशकिस्मती।


0
Add Following methods in ur code for getting correct size of attribute string 
1.
    - (CGFloat)findHeightForText:(NSAttributedString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font
 {
    UITextView *textView = [[UITextView alloc] init];
    [textView setAttributedText:text];
    [textView setFont:font];
    CGSize size = [textView sizeThatFits:CGSizeMake(widthValue, FLT_MAX)];
    return size.height;

}

2. Call on heightForRowAtIndexPath method
     int h = [self findHeightForText:attrString havingWidth:yourScreenWidth andFont:urFont];

मेरे मामले में मुझे बैकग्राउंड थ्रेड पर गणना करनी चाहिए, और यूआई तत्वों के उपयोग की अनुमति नहीं है
लब्बू

0

मैं अपने विचार जोड़ना चाहूंगा क्योंकि मेरे पास बिल्कुल यही समस्या थी।

मैं इसका उपयोग कर रहा था, UITextViewक्योंकि इसमें अच्छे पाठ संरेखण (औचित्य था, जो उस समय उपलब्ध नहीं था UILabel), लेकिन गैर-संवादात्मक-गैर-स्क्रॉल करने योग्य "अनुकरण" करने के लिए UILabel, मैं पूरी तरह से स्क्रॉलिंग, बाउंसिंग और उपयोगकर्ता इंटरैक्शन को बंद कर दूंगा ।

बेशक, समस्या यह थी कि पाठ गतिशील था, और जब चौड़ाई तय हो जाएगी, तो हर बार जब मुझे नया पाठ मान सेट करना होगा, तो ऊँचाई पुनर्गणना होनी चाहिए।

boundingRectWithSizeमेरे लिए बिल्कुल भी अच्छा काम नहीं किया, जो कुछ भी मैं देख सकता UITextViewथा , वह शीर्ष पर कुछ मार्जिन जोड़ रहा था जो boundingRectWithSizeएक गिनती में नहीं आएगा, इसलिए, जिस ऊंचाई से प्राप्त किया boundingRectWithSizeगया था वह उससे छोटा होना चाहिए।

चूंकि टेक्स्ट को तेजी से अपडेट नहीं किया जाना था, इसलिए इसका उपयोग केवल कुछ सूचनाओं के लिए किया जाता है जो हर 2-3 सेकंड में सबसे अधिक अपडेट हो सकती हैं, मैंने निम्नलिखित दृष्टिकोण का फैसला किया है:

/* This f is nested in a custom UIView-inherited class that is built using xib file */
-(void) setTextAndAutoSize:(NSString*)text inTextView:(UITextView*)tv
{
    CGFloat msgWidth = tv.frame.size.width; // get target's width

    // Make "test" UITextView to calculate correct size
    UITextView *temp = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, msgWidth, 300)]; // we set some height, really doesn't matter, just put some value like this one.
    // Set all font and text related parameters to be exact as the ones in targeted text view
    [temp setFont:tv.font];
    [temp setTextAlignment:tv.textAlignment];
    [temp setTextColor:tv.textColor];
    [temp setText:text];

    // Ask for size that fits :P
    CGSize tv_size = [temp sizeThatFits:CGSizeMake(msgWidth, 300)];

    // kill this "test" UITextView, it's purpose is over
    [temp release];
    temp = nil;

    // apply calculated size. if calcualted width differs, I choose to ignore it anyway and use only height because I want to have width absolutely fixed to designed value
    tv.frame = CGRectMake(tv.frame.origin.x, tv.frame.origin.y, msgWidth, tv_size.height );
}

* उपरोक्त कोड सीधे मेरे स्रोत से कॉपी नहीं किया गया है, मुझे इसे इस लेख के लिए आवश्यक अन्य सामान के गुच्छा से समायोजित / साफ़ करना था। इसे कॉपी-पेस्ट-एंड-इट-विल-वर्क-कोड के लिए न लें।

स्पष्ट नुकसान यह है कि यह प्रत्येक कॉल के लिए आवंटित और जारी किया गया है।

लेकिन, लाभ यह है कि आप कैसे boundingRectWithSize पाठ और गणना ड्रॉ के बीच संगतता के आधार पर से बचने है यह के आकार और में पाठ ड्राइंग के कार्यान्वयन UITextView(या UILabelजो भी आप बस की जगह उपयोग कर सकते हैं UITextViewके साथ UILabel)। कोई भी "बग" जो कि Apple का हो सकता है, इस तरह से बचा जा सकता है।

PS ऐसा लगता है कि आपको इस "अस्थायी" की आवश्यकता नहीं है UITextViewऔर यह sizeThatFitsसीधे लक्ष्य से पूछ सकता है, हालांकि यह मेरे लिए काम नहीं करता था। यद्यपि तर्क यह कहता है कि इसे काम करना चाहिए और अस्थायी आवंटन / आवंटन की UITextViewआवश्यकता नहीं है, यह नहीं किया। लेकिन यह समाधान मेरे द्वारा निर्धारित किसी भी पाठ के लिए त्रुटिपूर्ण काम करता है।


मेरे मामले में मुझे बैकग्राउंड थ्रेड पर गणना करनी चाहिए, और यूआई तत्वों के उपयोग की अनुमति नहीं है
लब्बू

0

ठीक है, इसलिए मैंने इसे डिबग करने में बहुत समय बिताया। मुझे पता चला कि boundingRectWithSizeमेरे द्वारा पाठ को प्रदर्शित करने की अनुमति द्वारा परिभाषित अधिकतम पाठ ऊंचाई UITextViewफ्रेम आकार से कम थी।

मेरे मामले में फ्रेम सबसे अधिक 140pt पर है, लेकिन UITextView अधिकांश 131pt पर ग्रंथों को सहन करता है।

मुझे यह पता लगाना था कि मैन्युअल रूप से और "वास्तविक" अधिकतम ऊंचाई हार्डकोड करें।

यहाँ मेरा समाधान है:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSString *proposedText = [textView.text stringByReplacingCharactersInRange:range withString:text];
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:proposedText];
    CGRect boundingRect;
    CGFloat maxFontSize = 100;
    CGFloat minFontSize = 30;
    CGFloat fontSize = maxFontSize + 1;
    BOOL fit;
    NSLog(@"Trying text: \"%@\"", proposedText);
    do {
        fontSize -= 1;
        //XXX Seems like trailing whitespaces count for 0. find a workaround
        [attributedText addAttribute:NSFontAttributeName value:[textView.font fontWithSize:fontSize] range:NSMakeRange(0, attributedText.length)];
        CGFloat padding = textView.textContainer.lineFragmentPadding;
        CGSize boundingSize = CGSizeMake(textView.frame.size.width - padding * 2, CGFLOAT_MAX);
        boundingRect = [attributedText boundingRectWithSize:boundingSize options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading context:nil];
        NSLog(@"bounding rect for font %f is %@; (max is %f %f). Padding: %f", fontSize, NSStringFromCGRect(boundingRect), textView.frame.size.width, 148.0, padding);
        fit =  boundingRect.size.height <= 131;
    } while (!fit && fontSize > minFontSize);
    if (fit) {
        self.textView.font = [self.textView.font fontWithSize:fontSize];
        NSLog(@"Fit!");
    } else {
        NSLog(@"No fit");
    }
    return fit;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.