iOS: ऑटो लेआउट में मल्टी-लाइन UILabel


183

मुझे ऑटो लेआउट के साथ कुछ बहुत ही बुनियादी लेआउट व्यवहार को प्राप्त करने में परेशानी हो रही है। मेरा दृश्य नियंत्रक आईबी में इस तरह दिखता है:

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

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

स्ट्रिंग द्वारा आवश्यक लाइनों की संख्या को फिट करने के लिए मैं शीर्षक लेबल कैसे प्राप्त कर सकता हूं? मेरी समझ यह है कि मैं सेटफ़्रेम विधियों का उपयोग नहीं कर सकता क्योंकि मैं ऑटो लेआउट का उपयोग कर रहा हूं। और मुझे ऑटो लेआउट का उपयोग करना होगा क्योंकि मुझे शीर्षक लेबल के नीचे रहने के लिए उन अन्य विचारों की आवश्यकता है (इसलिए बाधाएं)।

मैं यह कैसे कर सकता हूं?


3
मैं भी इसी तरह की समस्या से लड़ रहा हूं। लेकिन मैं अभी भी सामग्री को फिट करने के लिए अपनी ऊंचाई को गतिशील रूप से समायोजित करने के लिए शीर्ष लेबल प्राप्त करने के लिए संघर्ष कर रहा हूं। आपने इसे कैसे हासिल किया?
jbandi

1
कृपया @ mwhuss के उत्तर को मानने के रूप में स्वीकार करें।
जेमन्स

1
क्या आपने आवश्यक परिणाम प्राप्त किया?
अनिरुद्ध

यह जांचें, आपको कोड stackoverflow.com/a/36862795/4910767
बादल शाह

जवाबों:


254

और autolayout -setPreferredMaxLayoutWidthपर उपयोग UILabelबाकी को संभालना चाहिए।

[label setPreferredMaxLayoutWidth:200.0];

पसंदीदामैक्सलायआउट पर यूआईबेल प्रलेखन देखें ।

अपडेट करें:

केवल heightस्टोरीबोर्ड में बाधा को सेट करने की आवश्यकता है Greater than or equal to, कोई सेट करने की आवश्यकता नहीं हैPreferredMaxLayoutWidth।


8
वैसे भी, इंटरफ़ेस बिल्डर में ऐसा करने के लिए अच्छा है?
सोज़र्ड परफ़ॉर्मर्स

12
इसके अलावा आईबी में ग्रेटर बाधा निर्धारित करें "के बराबर या उससे अधिक"।
जौं

10
अनुस्मारक: कृपया याद रखें कि नंबरऑफ़लाइन संपत्ति सेट करें।
ली फ्यूमिन

2
हां, आप जो भी अधिकतम चौड़ाई चाहते हैं उसका उपयोग करें।
मिस

4
देखें stackoverflow.com/a/29180323/1529675 कैसे निर्धारित करने के लिए preferredMaxLayoutWidthऔर देखो devetc.org/code/2014/07/07/auto-layout-and-views-that-wrap.html एक संक्षिप्त लेकिन सूचनात्मक writeup के लिए, के साथ पूरा एनिमेटेड GIF (मेरा
राइटअप

213

अपने लेबल सेट लाइनों की संख्या को 0 तक विस्तारित करें और ऑटो लेआउट सेट ऊंचाई के लिए> = x के लिए और भी अधिक महत्वपूर्ण है। ऑटो लेआउट बाकी काम करेगा। आप अपने अन्य तत्वों को पिछले तत्व के आधार पर सही ढंग से स्थिति में शामिल कर सकते हैं।

ऑटो लेआउट


यदि यह विधि आपके लिए काम नहीं करती है, तो कृपया Cory Imdieke का उत्तर सुनिश्चित करें कि बाद के विचारों के बारे में ऑटो लेआउट को (संभवतः) बहुस्तरीय दृश्य के आकार बदलने से प्रतिबंधित न करें।
टॉम हावर्ड

1
यह एकमात्र उत्तर है जिसने मेरे लिए एक टेबल व्यू सेल में काम किया है। इसके अलावा एक निश्चित संख्या में पंक्तियों के साथ काम करता है (0 / असीमित के बजाय)
bgolson

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

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

1
यह मेरे लिए काम नहीं किया। मेरा मानना ​​है कि stackoverflow.com/a/13032251/1529675 सही उत्तर है।
tboyce12

48

स्रोत: http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html

मल्टी-लाइन टेक्स्ट का आंतरिक सामग्री आकार

UILabel और NSTextField की आंतरिक सामग्री का आकार बहु-पंक्ति पाठ के लिए अस्पष्ट है। पाठ की ऊंचाई लाइनों की चौड़ाई पर निर्भर करती है, जो बाधाओं को हल करते समय निर्धारित किया जाना बाकी है। इस समस्या को हल करने के लिए, दोनों वर्गों के पास एक नई प्रॉपर्टी है, जिसे पसंदीदामैक्लेयविथ कहा जाता है, जो आंतरिक सामग्री आकार की गणना के लिए अधिकतम लाइन चौड़ाई निर्दिष्ट करता है।

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

- (void)layoutSubviews
{
    [super layoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [super layoutSubviews];
}

[सुपर लेआउटसुब्यू] के लिए पहला कॉल लेबल के लिए आवश्यक है कि उसका फ्रेम सेट हो, जबकि दूसरा कॉल परिवर्तन के बाद लेआउट को अपडेट करने के लिए आवश्यक है। यदि हम दूसरी कॉल को छोड़ देते हैं तो हमें NSInternalInconsistencyException त्रुटि मिलती है, क्योंकि हमने लेआउट पास में बदलाव किए हैं, जिन्हें बाधाओं को अपडेट करने की आवश्यकता होती है, लेकिन हमने लेआउट को फिर से ट्रिगर नहीं किया।

हम इसे स्वयं लेबल उपवर्ग में भी कर सकते हैं:

@implementation MyLabel
- (void)layoutSubviews
{
    self.preferredMaxLayoutWidth = self.frame.size.width;
    [super layoutSubviews];
}
@end

इस मामले में, हमें पहले [सुपर लेआउटसुब्यू] को कॉल करने की आवश्यकता नहीं है, क्योंकि जब लेआउटसुब्यू कहा जाता है, तो हमारे पास पहले से ही लेबल पर एक फ्रेम है।

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

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [self.view layoutIfNeeded];
}

अंत में, सुनिश्चित करें कि आपके पास लेबल पर एक स्पष्ट ऊंचाई की कमी नहीं है, जिसमें लेबल की सामग्री संपीड़न प्रतिरोध प्राथमिकता से अधिक प्राथमिकता है। अन्यथा यह सामग्री की गणना की गई ऊँचाई को काट देगा। सभी बाधाओं की जांच करना सुनिश्चित करें जो लेबल की ऊंचाई को प्रभावित कर सकते हैं।


धन्यवाद न केवल कोड के लिए धन्यवाद, बल्कि इससे भी महत्वपूर्ण बात यह है कि स्पष्टीकरण और उदाहरण यह है कि यह कैसे करना है न केवल एक उपवर्ग में, बल्कि दृश्य नियंत्रक से भी।
djibouti33

मैं अपने दृश्य नियंत्रक में यह कोशिश कर रहा हूं, और viewDidLayoutSubviews viewWillAppear और viewDidAppear के बाद कॉल किया जा रहा है। ViewDidAppear के बाद, जब लेबल सही ढंग से रिसाइज़ हो जाते हैं तो फ्लैश होता है। क्या इससे बचने का कोई तरीका है? क्या उपयोगकर्ता को कुछ भी देखने से पहले आकार बदलने का एक तरीका है? मेरे मामले में, मेरे मल्टी-लाइन लेबल एक टेबलहैडर व्यू में हैं, और इसलिए मैं इस उदाहरण का उपयोग करके लेबल के आधार पर हेडर दृश्य की ऊंचाई का आकार बदल रहा हूं ( stackoverflow.com/questions/20982558/… )
djibeti33

@ djibouti33 क्या आप न्यूनतम नमूना कोड प्रदान कर सकते हैं (उदाहरण के लिए जीथब रेपो के रूप में) ताकि मैं आसानी से इस मुद्दे की जांच कर सकूं?
एंटोन माटोसोव

धन्यवाद @ एटन। तब से हमारा डिज़ाइन UITableView से UICollectionView में बदल गया है, और सौभाग्य से मैंने यह व्यवहार नहीं देखा। यदि मैं एक छोटा सा नमूना प्रोजेक्ट बनाने के लिए अपने गिट इतिहास पर प्राप्त कर सकता हूं, तो मैं आपको बता दूंगा।
djibouti33

जब से मैंने iOS 9 सिम पर चलना शुरू किया था तब से ही मेरे लिए एक समस्या थी लेकिन जब मैंने iOS 8 पर परीक्षण किया तो परेशानी शुरू हो गई। मुझे मैन्युअल रूप से अधिकतम चौड़ाई सेट करने की आवश्यकता है।
naz

17

मैं सिर्फ इस सटीक परिदृश्य के साथ लड़ रहा था, लेकिन कुछ और विचारों के साथ जो आवश्यक होने पर आकार बदलने और नीचे जाने के लिए आवश्यक थे। यह मुझे पागल कर रहा था, लेकिन मैंने आखिरकार इसका पता लगा लिया।

यहाँ कुंजी है: इंटरफ़ेस बिल्डर अतिरिक्त बाधाओं को फेंकना पसंद करता है जैसा कि आप जोड़ते और देखते हैं और आप नोटिस नहीं कर सकते हैं। मेरे मामले में, मेरे पास एक आधा रास्ता था, जिसमें एक अतिरिक्त बाधा थी जो इसके और इसके पर्यवेक्षण के बीच के आकार को निर्दिष्ट करती थी, मूल रूप से इसे उस बिंदु पर पिन करती थी। इसका मतलब था कि इसके ऊपर का कुछ भी बड़ा आकार नहीं बदल सकता क्योंकि यह उस बाधा के खिलाफ जाएगा।

यह बताने का एक आसान तरीका है कि क्या यह मामला लेबल को मैन्युअल रूप से आकार देने की कोशिश कर रहा है। क्या आईबी आपको इसे बढ़ने देती है? यदि ऐसा होता है, तो क्या नीचे के लेबल आपकी अपेक्षा के अनुरूप चलते हैं? यह सुनिश्चित करने के लिए कि आपके पास यह देखने से पहले कि आपके अवरोधक आपके विचार को कैसे आगे बढ़ाएंगे, इन दोनों की जाँच करें।

आईबी मेनू

यदि दृश्य अटका हुआ है, तो नीचे दिए गए विचारों का पालन करें और सुनिश्चित करें कि उनमें से एक में पर्यवेक्षणीय बाधा के लिए एक शीर्ष स्थान नहीं है। फिर बस यह सुनिश्चित कर लें कि लेबल के लिए आपकी लाइनों का विकल्प 0 पर सेट है और इसे बाकी का ध्यान रखना चाहिए।


हां, इसके साथ बहुत खेलने के बाद मैं वह प्रभाव प्राप्त करने में सक्षम था जो मैं चाहता था। आपको केवल उन बाधाओं के बारे में बहुत सावधानी से सोचना होगा जो आप चाहते हैं। यह मदद नहीं करता है कि आईबी लगातार उन बाधाओं में फेंक रही है जिनकी आपको उम्मीद नहीं है।
जेम्स हार्प

5

मुझे लगता है कि आपको निम्नलिखित की आवश्यकता है:

  • एक शीर्ष बाधा
  • एक प्रमुख बाधा (जैसे बाईं ओर)
  • एक अनुगामी बाधा (जैसे दाईं ओर)
  • सामग्री हगिंग प्राथमिकता, क्षैतिज से निम्न पर सेट करें, ताकि पाठ छोटा होने पर यह दिए गए स्थान को भर दे।
  • सामग्री कम्प्रेशन प्रतिरोध, क्षैतिज से निम्न पर सेट करें, ताकि यह व्यापक बनने की कोशिश के बजाय लपेटे।
  • रेखाओं की संख्या को 0 पर सेट करें।
  • वर्ड रैप के लिए लाइन ब्रेक मोड सेट करें।

यह xcode9 में काम करना चाहिए। मुझे लेबल ऊंचाई की कमी के साथ कुछ भी करने की ज़रूरत नहीं थी (मेरे पास कोई नहीं है): यह सिर्फ एक बार बॉक्स से बाहर काम करता है जब लेबल बंद हो जाएगा (अनुगामी, अग्रणी, ऊपर और नीचे)। uikit बाकी
एंटोन ट्रोपास्को

प्राथमिकता को गले लगाने वाली सामग्री मेरी समस्या थी। मुझे उस संपत्ति के साथ-साथ संपीड़न प्रतिरोध से अवगत कराने के लिए धन्यवाद। आपने मुझे एक घंटे की समस्या को हल करने में मदद की।
डेविड गे

0

विषय पर कई विषयों में पाए गए विभिन्न समाधानों में से किसी ने भी मेरे मामले के लिए पूरी तरह से काम नहीं किया (डायनेमिक टेबल व्यू कोशिकाओं में एक्स डायनामिक मल्टीलाइन लेबल)।

मुझे यह करने का एक तरीका मिला:

अपने लेबल पर बाधाओं को निर्धारित करने और अपनी बहु-संपत्ति को 0 पर सेट करने के बाद, यूबेल का उपवर्ग बनाएं; मुझे मेरा नाम AutoLayoutLabel:

@implementation AutoLayoutLabel

- (void)layoutSubviews{
    [self setNeedsUpdateConstraints];
    [super layoutSubviews];
    self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
}

@end

0

मेरे पास एक UITableViewCell है जिसमें एक टेक्स्ट रैप लेबल है। मैंने निम्नानुसार पाठ रैपिंग का काम किया।

1) इस प्रकार के रूप में सेट UILabel बाधाओं।

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

2) सेट नं। 0 की लाइनों।

3) UITableViewCell में UILabel height constraint जोड़ा गया।

@IBOutlet weak var priorityLabelWidth: NSLayoutConstraint!

4) UITableViewCell पर:

priorityLabel.sizeToFit()
priorityLabelWidth.constant = priorityLabel.intrinsicContentSize().width+5

-12

ऐसा करने का एक तरीका ... जैसे-जैसे पाठ की लंबाई बढ़ती जाती है, वैसे-वैसे लेबल पाठ के फोंटाइज़ को बदलने (घटाने) की कोशिश करते हैं

Label.adjustsFontSizeToFitWidth = YES;

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