UILabel sizeToFit ऑटोलेयूट ios6 के साथ काम नहीं करता है


152

मैं एक UILabel जिसकी ऊंचाई उसके पाठ पर निर्भर करती है, प्रोग्रामेटिकली (और किस विधि में) कॉन्फ़िगर करने वाली हूं? मैं स्टोरीबोर्ड और कोड के संयोजन का उपयोग करके इसे स्थापित करने की कोशिश कर रहा हूं, लेकिन कोई फायदा नहीं हुआ। हर कोई सिफारिश की गई है sizeToFit, जबकि स्थापित करने lineBreakModeऔर numberOfLines। हालांकि, कोई बात नहीं अगर मैं उस कोड को अंदर viewDidLoad:डालूं viewDidAppear:, या viewDidLayoutSubviewsमैं इसे काम नहीं कर सकता। या तो मैं बॉक्स को लंबे पाठ के लिए बहुत छोटा बनाता हूं और यह बढ़ता नहीं है, या मैं इसे बहुत बड़ा बनाता हूं और यह सिकुड़ता नहीं है।


FWIW एक ही कोड: मुझे label.sizeToFit()Xcode / viewController में उपयोग करने की आवश्यकता नहीं थी , बाधाएं पर्याप्त थीं। खेल के मैदान में लेबल नहीं बना रहा था । अभी तक मुझे प्लेग्राउंड में काम करने का एकमात्र तरीका हैlabel.sizeToFit()
हनी

जवाबों:


407

कृपया ध्यान दें कि ज्यादातर मामलों में मैट के समाधान उम्मीद के काम करता है। लेकिन अगर यह आपके लिए काम नहीं करता है, तो कृपया आगे पढ़ें।

अपना लेबल स्वचालित रूप से आकार बदलने के लिए आपको निम्न कार्य करने की आवश्यकता है:

  1. लेबल के लिए लेआउट बाधाएं सेट करें
  2. कम प्राथमिकता के साथ ऊंचाई की सीमा निर्धारित करें। यह ContentCompressionResistancePriority से कम होना चाहिए
  3. संख्या निर्धारित करें = 0
  4. लेबल की ऊंचाई प्राथमिकता की तुलना में ContentHuggingPriority को सेट करें
  5. लेबल के लिए पसंदीदामेक् लॉयआउट को सेट करें। उस मूल्य का उपयोग लेबल द्वारा इसकी ऊंचाई की गणना करने के लिए किया जाता है

उदाहरण के लिए:

self.descriptionLabel = [[UILabel alloc] init];
self.descriptionLabel.numberOfLines = 0;
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.descriptionLabel.preferredMaxLayoutWidth = 200;

[self.descriptionLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.descriptionLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.descriptionLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:self.descriptionLabel];

NSArray* constrs = [NSLayoutConstraint constraintsWithVisualFormat:@"|-8-[descriptionLabel_]-8-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)];
[self addConstraints:constrs];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[descriptionLabel_]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];
[self.descriptionLabel addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[descriptionLabel_(220@300)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];

इंटरफ़ेस बिल्डर का उपयोग करना

  1. चार अड़चनें खड़ी करें। ऊंचाई की कमी अनिवार्य है। यहाँ छवि विवरण दर्ज करें

  2. फिर लेबल के गुण निरीक्षक पर जाएं और लाइनों की संख्या 0 पर सेट करें। यहाँ छवि विवरण दर्ज करें

  3. लेबल के आकार निरीक्षक पर जाएं और वर्टिकल कंटेंटहॉगिंगपैरिटी और वर्टिकल कंटेंटकंप्रेसनैसिस्टेंसपैरिटी बढ़ाएं।
    यहाँ छवि विवरण दर्ज करें

  4. ऊंचाई की कमी का चयन करें और संपादित करें।
    यहाँ छवि विवरण दर्ज करें

  5. और ऊंचाई की कमी को प्राथमिकता दें।
    यहाँ छवि विवरण दर्ज करें

का आनंद लें। :)


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

43
आप इसे खत्म कर रहे हैं। या तो preferredMaxLayoutWidthलेबल की चौड़ाई सेट करें या पिन (या उसके दाईं और बाईं ओर)। बस इतना ही! यह तब स्वचालित रूप से बढ़ता है और इसकी सामग्री को फिट करने के लिए लंबवत सिकुड़ता है।
मैट

मुझे पसंदीदामैक्स लाईआउटविथ प्रॉपर्टी सेट करनी होगी + लेबल की चौड़ाई पिन करें। एक आकर्षण की तरह काम करता है :)
मार्टिनोमोइक

पसंदीदामैक्सआउटआउट और / या बाईं और दाईं ओर पिनिंग निरपेक्ष नहीं है। कंटेंट हगिंग और कम्प्रेशन प्राथमिकताएँ हमेशा तब तक काम करेंगी जब तक उनकी प्राथमिकताएँ बाकी बाधाओं से अधिक हों।
एरिक अल्फोर्ड

2
^ और मुझे अंत में पता चला कि क्यों, उल्लेख के लायक हो सकता है, जब आपके पास सेल को देखने के तल पर चिपके रहते हैं, तो आपको "नीचे से नीचे" की प्राथमिकता को कम से कम करने की प्राथमिकता निर्धारित करने की आवश्यकता है, तो 1000 मैंने इसे 750 पर रखा। सब कुछ पूरी तरह से काम कर रहा है। मुझे लगता है कि यह दृश्य सिकुड़ गया।
मथिजर्स

65

IOS 6 में, ऑटोलैयूट का उपयोग करते हुए, यदि एक उइलैबेल के किनारों (या चौड़ाई) और शीर्ष को पिन किया जाता है, तो यह अपनी सामग्री को फिट करने के लिए स्वचालित रूप से बढ़ेगा और सिकुड़ जाएगा , जिसमें कोई भी कोड नहीं है और इसके संपीड़न प्रतिरोध या जो भी हो , के साथ कोई गड़बड़ नहीं है। यह मृत सरल है।

अधिक जटिल मामलों में, बस लेबल सेट करें preferredMaxLayoutWidth

किसी भी तरह से, सही बात अपने आप हो जाती है।


12
तुम भी 0 करने के लिए numberOfLines सेट करने के लिए सुनिश्चित करने की आवश्यकता है अन्यथा आप लपेटन नहीं मिलेगा।
devongovett

2
यह मेरे लिए पर्याप्त नहीं था। @ मार्क के उत्तर से भी बिंदु 2 की आवश्यकता है।
डेनियल आयटेकिन

क्या यह भी संभव है कि कोड लिखे बिना लेबल कई लाइनों पर स्वचालित रूप से बढ़ता है?
नूर

यह स्वीकृत उत्तर की तुलना में बहुत कम जटिल है। मैंने इस उत्तर को स्पष्ट करते हुए दो उदाहरण ( यहाँ और यहाँ ) दिए हैं।
सुरगाछ

@Suragch इस कार्य में बाधा का उपयोग कर रहा है। लेकिन यह प्लेग्राउंड में समान कोड के लिए काम नहीं करता है । खेल के मैदान में आपके पास होना चाहिएlabel.sizeToFit()
Honey

42

हालाँकि यह सवाल प्रोग्रामेटिक रूप से बताता है, एक ही समस्या का सामना करना पड़ रहा है, और इंटरफ़ेस बिल्डर में काम करना पसंद कर रहा है, मैंने सोचा कि यह एक इंटरफ़ेस बिल्डर समाधान के साथ मौजूदा उत्तरों को जोड़ना उपयोगी हो सकता है।

पहली बात तो भूल जाना है sizeToFit । ऑटो लेआउट आंतरिक सामग्री के आकार के आधार पर इसे आपकी ओर से हैंडल करेगा।

इसलिए समस्या यह है कि ऑटो लेआउट के साथ संतुष्ट होने के लिए लेबल कैसे प्राप्त करें? विशेष रूप से - क्योंकि प्रश्न में इसका उल्लेख है - ऊंचाई। ध्यान दें कि समान सिद्धांत चौड़ाई पर लागू होते हैं।

तो चलिए एक उदाहरण से शुरू करते हैं UILabel कि ऊंचाई 41px तक है:

यहाँ छवि विवरण दर्ज करें

जैसा कि आप ऊपर दिए गए स्क्रीन ग्रैब में देख सकते हैं, "This is my text"ऊपर और नीचे पैडिंग है। यह उइबेल की ऊंचाई के बीच पैडिंग है, और यह सामग्री, पाठ है।

यदि हम सिम्युलेटर में ऐप चलाते हैं, तो निश्चित रूप से, हम एक ही चीज़ देखते हैं:

यहाँ छवि विवरण दर्ज करें

अब, आइये इंटरफ़ेस बिल्डर में UILabel का चयन करें, और आकार निरीक्षक में डिफ़ॉल्ट सेटिंग्स पर एक नज़र डालें:

यहाँ छवि विवरण दर्ज करें

ऊपर उल्लिखित बाधा पर ध्यान दें। वह कंटेंट हगिंग प्रायरिटी है । जैसा कि एरिका सदून ने उत्कृष्ट आईओएस ऑटो लेआउट में इसका वर्णन किया है , यह है:

जिस तरह से यह मूल सामग्री के आसपास अतिरिक्त पैडिंग से बचने के लिए एक दृश्य पसंद करता है

हमारे लिए, यूबिल के साथ, मूल सामग्री पाठ है।

यहाँ हम इस मूल परिदृश्य के दिल में आते हैं। हमने अपने टेक्स्ट लेबल को दो अड़चनें दी हैं। वे संघर्ष करते हैं। एक का कहना है "ऊंचाई 41 पिक्सेल के बराबर होनी चाहिए" । दूसरे कहते हैं, "यह सामग्री को देखने के लिए गले लगाओ ताकि हमारे पास कोई अतिरिक्त गद्दी न हो" । हमारे मामले में, यह पाठ को देखने के लिए गले लगाओ ताकि हमारे पास कोई अतिरिक्त गद्दी न हो।

अब, ऑटो लेआउट के साथ, दो अलग-अलग निर्देशों के साथ जो अलग-अलग काम करते हैं, रनटाइम को एक या दूसरे को चुनना होगा। यह दोनों नहीं कर सकते। यूआईबेल 41 पिक्सेल उच्च और दोनों नहीं हो सकता है कोई पैडिंग नहीं है।

जिस तरह से इसे हल किया गया है, प्राथमिकता को निर्दिष्ट करके है। एक निर्देश के लिए दूसरे की तुलना में उच्च प्राथमिकता होनी चाहिए। यदि दोनों निर्देश अलग-अलग बातें कहते हैं, और समान प्राथमिकता है, तो एक अपवाद होगा।

तो चलिए हम इसे देते हैं। मेरे कद की बाधा 1000 की प्राथमिकता है , जिसकी आवश्यकता है । कंटेंट हगिंग की ऊंचाई 250 है , जो कमजोर है । यदि हम ऊंचाई की बाधा को 249 तक कम कर दें तो क्या होगा ?

यहाँ छवि विवरण दर्ज करें

अब हम जादू की शुरुआत देख सकते हैं। आइए सिम में कोशिश करते हैं:

यहाँ छवि विवरण दर्ज करें

बहुत बढ़िया! कंटेंट हगिंग हासिल की। केवल इसलिए कि ऊँचाई प्राथमिकता 249 सामग्री हगिंग प्राथमिकता 250 से कम है । मूल रूप से, मैं कह रहा हूँ "मेरे द्वारा निर्दिष्ट ऊँचाई सामग्री हगिंग के लिए मेरे द्वारा निर्दिष्ट की गई तुलना में कम महत्वपूर्ण है" । तो, सामग्री हगिंग जीत जाती है।

निचला रेखा, पाठ को फिट करने के लिए लेबल प्राप्त करना उतनी ही सरल हो सकता है जितना कि ऊँचाई - या चौड़ाई - बाधा को निर्दिष्ट करना और उस अक्ष की सामग्री के साथ प्राथमिकता प्राथमिकता बाधा को सही करना।

पाठक के लिए एक अभ्यास के रूप में चौड़ाई के बराबर करना छोड़ देंगे!


3
आपके महान स्पष्टीकरण के लिए बहुत बहुत धन्यवाद! अंत में मैं कंटेंट हगिंग प्रायरिटी को समझता हूं।
kernix

क्या आप यह भी बता सकते हैं कि सामग्री संपीड़न प्रतिरोध प्राथमिकता क्या है? धन्यवाद!
kernix

2
एक्सेलेंटे जवाब मैक्स! क्या इस तरह काम करने वाली लाइनों की संख्या को सीमित करने के लिए कोई है?
राफेलजुजो

7

IOS7 आकार में नोट किया गया था। यह भी काम नहीं कर रहा था - शायद समाधान भी आपकी मदद कर सकता है

[textView sizeToFit];
[textView layoutIfNeeded];

1
@ रामबेटिनो यह मेरे लिए काम करता है। layoutIfNeededजरूरत पड़ने पर जोड़ें setNeedsUpdateConstraints। लेकिन स्थिति थोड़ी अलग हो सकती है।
गॉन

मेरे लिए यह सबसे अच्छा था जब मैंने एक पॉपओवर किया। मुझे लेआउट करने की जरूरत थी। पहले-पहल, हालांकि
जेसन

4

लेबल की पसंद को सुनिश्चित करने के लिए एक अन्य विकल्पमैक्लायआउट को लेबल की चौड़ाई के साथ सिंक में रखा गया है:

#import "MyLabel.h"

@implementation MyLabel

-(void)setBounds:(CGRect)bounds
{
    [super setBounds:bounds];

    // This appears to be needed for iOS 6 which doesn't seem to keep
    // label preferredMaxLayoutWidth in sync with its width, which 
    // means the label won't grow vertically to encompass its text if 
    // the label's width constraint changes.
    self.preferredMaxLayoutWidth = self.bounds.size.width;
}

@end

4

मुझे लगता है कि मुझे सही समाधान खोजने में कुछ समय लगना चाहिए क्योंकि मुझे इसमें योगदान करना चाहिए:

  • लक्ष्य यह है कि ऑटो लेआउट को कभी भी आकार दिए बिना अपना काम करने दिया जाए। फ़ाइट (), हम सही बाधाओं को निर्दिष्ट करके ऐसा करेंगे:
  • अपने UILabel पर स्पेस, टॉप और बॉटम और ट्रेलिंग स्पेस की कमी को निर्दिष्ट करें
  • लाइनों की संपत्ति की संख्या 0 पर सेट करें
  • 1000 की सामग्री आलिंगन प्राथमिकता में वृद्धि
  • सामग्री संपीड़न प्रतिरोध प्राथमिकता को 500 तक कम करें
  • अपने निचले कंटेनर बाधा पर, प्राथमिकता को 500 तक कम करें

मूल रूप से, ऐसा क्या होता है कि आप अपने यूआईलेबेल को बताते हैं कि भले ही इसकी एक निश्चित ऊंचाई बाधा है, यह सामग्री को गले लगाने के लिए खुद को छोटा बनाने के लिए बाधा को तोड़ सकता है (यदि आपके पास उदाहरण के लिए एक ही पंक्ति है), लेकिन नहीं कर सकता इसे बड़ा करने के लिए बाधा को तोड़ें।


3

मेरे मामले में मैं एक यूआईईवीवाई उपवर्ग बना रहा था जिसमें एक यूआईबेल (अज्ञात लंबाई का) था। IOS7 में कोड सीधा था: बाधाओं को सेट करें, कंटेंट हगिंग या कम्प्रेशन रेजिस्टेंस के बारे में चिंता न करें, और सब कुछ उम्मीद के मुताबिक काम किया।

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

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

- (void)layoutSubviews
{
    // Autolayout hack required for iOS6
    [super layoutSubviews];
    self.bodyLabel.preferredMaxLayoutWidth = self.bodyLabel.frame.size.width;
    [super layoutSubviews];
}

यह सटीक परिदृश्य था जो मेरे पास था ... कभी-कभी यह जानकर अच्छा लगता है कि आप अकेले नहीं हैं।
daveMac 24/14

एडम, आपने ios7 में पूरी तरह से काम करने के बारे में कहा। मेरे पास एक uiview और एक uilabel के साथ एक कस्टम सेल है। मुझे सामग्री फिट करने के लिए लेबल मिल सकता है लेकिन दृश्य ऐसा नहीं है, इससे कोई फर्क नहीं पड़ता कि मैं इस पर क्या दबाव डालता हूं। तुमने इससे काम कैसे लिया? मुझे लगता है कि मैंने सब कुछ करने की कोशिश की, लेकिन यह लेबल की ऊँचाई नहीं लेता है
denikov

3

मैंने UILabelप्रोग्रामेटिक रूप से और अपने मामले में जोड़ा जो कि पर्याप्त था:

label.translatesAutoresizingMaskIntoConstraints = false
label.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Vertical)
label.numberOfLines = 0

2

मैंने xCode6 के साथ "पसंदीदा चौड़ाई" को स्वचालित और लेबल शीर्ष को पिन करने, अग्रणी और अनुगामी बनाने के साथ हल किया है यहाँ छवि विवरण दर्ज करें


0
UIFont *customFont = myLabel.font;
CGSize size = [trackerStr sizeWithFont:customFont
                             constrainedToSize:myLabel.frame.size // the size here should be the maximum size you want give to the label
                                 lineBreakMode:UILineBreakModeWordWrap];
float numberOfLines = size.height / customFont.lineHeight;
myLabel.numberOfLines = numberOfLines;
myLabel.frame = CGRectMake(258, 18, 224, (numberOfLines * customFont.lineHeight));

0

मैं इस समस्या के साथ-साथ एक UIView उपवर्ग के साथ भाग गया जिसमें एक UILabel शामिल है यदि इसके आंतरिक तत्व। यहां तक ​​कि ऑटोलेयआउट और सभी अनुशंसित समाधानों की कोशिश के साथ, लेबल सिर्फ पाठ को इसकी ऊंचाई को कसने नहीं देगा। मेरे मामले में, मैं केवल यही चाहता हूं कि लेबल एक पंक्ति में हो।

वैसे भी, मेरे लिए जो काम किया गया, वह था यूबिल के लिए एक आवश्यक ऊँचाई की बाधा को जोड़ना और इसे आंतरिक रूप से सही ऊंचाई पर सेट करना जब आंतरिक आंतरिक संपर्क कहा जाता है। यदि आपके पास एक और UIVIV में निहित UILabel नहीं है, तो आप UILabel को उपवर्गित करने का प्रयास कर सकते हैं और पहले ऊँचाई की बाधा को निर्धारित करके और फिर
[सुपर इंस्ट्रेंसिककंटेसाइज़] वापस करके एक समान कार्यान्वयन प्रदान कर सकते हैं ; इसके बजाय [self.containerview intrinsiceContentSize]; जैसे मैं नीचे करता हूं जो मेरे यूविईवी सबलेट्स के लिए विशिष्ट है।

- (CGSize)intrinsicContentSize
{
    CGRect expectedTextBounds = [self.titleLabel textRectForBounds:self.titleLabel.bounds limitedToNumberOfLines:1];
    self.titleLabelHeightConstraint.constant = expectedTextBounds.size.height;
    return [self.containerView intrinsicContentSize];

}

IOS 7 और iOS 8 पर अब पूरी तरह से काम करता है।


यह ध्यान देने योग्य है कि यदि आपने अपना दृष्टिकोण सही तरीके से सेट किया है (यानी आपके अवरोध सही हैं और आपने दृश्य जीवन चक्र में सही चरणों के दौरान सब कुछ सेट किया है), तो आपको कभी भी ओवरराइड नहीं करना चाहिए intrinsicContentSize। रनटाइम को आपके सही सेटअप बाधाओं के आधार पर इसकी गणना करने में सक्षम होना चाहिए।
जॉन रोजर्स

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

... लेकिन [सुपर इंट्रेंसिक कॉन्टेंटसाइज़] को इसका ध्यान रखना चाहिए, मैं यही कह रहा हूं। यदि आपने अपना ऑटो लेआउट सही ढंग से लागू किया है।
जॉन रोजर्स

0

एक समाधान जो मेरे लिए काम करता था; अपने UILabel एक निश्चित चौड़ाई है, से बाधा को बदलने constant =के लिए constant <=अपने इंटरफेस फ़ाइल में

यहाँ छवि विवरण दर्ज करें


-1

मेरे मामले में, जब UITableViewCell में लेबल का उपयोग किया जाता है, तो लेबल आकार बदल जाता है, लेकिन ऊंचाई तालिका की ऊंचाई से अधिक हो जाएगी। इसी से मेरा काम बना है। मैंने मैक्स मैकलेओड के अनुसार किया, और फिर सुनिश्चित किया कि सेल की ऊँचाई यूआईटेबल व्यूऑटोमेटिकडिमेशन पर सेट की गई थी।

आप इसे अपने init या awakeFromNib में जोड़ सकते हैं,

self.tableView.rowHeight = UITableViewAutomaticDimension.  

स्टोरीबोर्ड में, सेल का चयन करें, आकार निरीक्षक खोलें, और सुनिश्चित करें कि 'कस्टम' चेकबॉक्स को ucheck करके पंक्ति की ऊंचाई "डिफ़ॉल्ट" पर सेट है।

8.0 में एक समस्या है जिसके लिए इसे कोड में सेट करना भी आवश्यक है।

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