ऑटो लेआउट का उपयोग करके UICollectionView में कोशिकाओं के एक आयाम को निर्दिष्ट करना


113

आईओएस 8 में UICollectionViewFlowLayoutअपने स्वयं के सामग्री आकार के आधार पर स्वचालित रूप से आकार बदलने वाली कोशिकाओं का समर्थन करता है। यह कोशिकाओं को उनकी सामग्री के अनुसार चौड़ाई और ऊंचाई दोनों में आकार देता है।

क्या सभी कोशिकाओं की चौड़ाई (या ऊंचाई) के लिए एक निश्चित मान निर्दिष्ट करना संभव है और अन्य आयामों का आकार बदलने की अनुमति है?

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


आईओएस 8 विधि का परिचय systemLayoutSizeFittingSize: withHorizontalFittingPriority: verticalFittingPriority:देता है संग्रह में प्रत्येक सेल के लिए लेआउट अनुमानित आकार में गुजरते हुए, सेल पर इस पद्धति को कॉल करता है। मुझे क्या समझ में आता है कि इस पद्धति को सेल पर ओवरराइड करना होगा, जो आकार में दिया गया है, पास दिया गया है और क्षैतिज बाधा को आवश्यक और ऊर्ध्वाधर बाधा को कम प्राथमिकता देना है। इस तरह क्षैतिज आकार लेआउट में निर्धारित मूल्य पर तय होता है और ऊर्ध्वाधर आकार लचीला हो सकता है।

कुछ इस तरह:

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    UICollectionViewLayoutAttributes *attributes = [super preferredLayoutAttributesFittingAttributes:layoutAttributes];
    attributes.size = [self systemLayoutSizeFittingSize:layoutAttributes.size withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel];
    return attributes;
}

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

क्या sizeइस पद्धति का पैरामीटर वास्तव में केवल दो स्थिरांक में पारित करने का एक तरीका है? क्या किसी व्यवहार को प्राप्त करने का कोई तरीका नहीं है जो मुझे दिए गए आकार के लिए उचित ऊंचाई पाने की उम्मीद है?


वैकल्पिक समाधान

1) उन बाधाओं को जोड़ना जो सेल के लिए एक विशिष्ट चौड़ाई निर्दिष्ट करेंगे, सही लेआउट प्राप्त करते हैं। यह एक खराब समाधान है क्योंकि उस बाधा को सेल के संग्रह दृश्य के आकार पर सेट किया जाना चाहिए, जिसका कोई सुरक्षित संदर्भ नहीं है। जब कक्ष को कॉन्फ़िगर किया जाता है, तो उस बाधा के लिए मूल्य पारित किया जा सकता है, लेकिन यह भी पूरी तरह से काउंटरिंटिव लगता है। यह भी अजीब है क्योंकि एक सेल में सीधे बाधाओं को जोड़ना या यह सामग्री दृश्य कई समस्याएं पैदा कर रहा है।

2) तालिका दृश्य का उपयोग करें। तालिका दृश्य इस तरह से बॉक्स से बाहर काम करते हैं क्योंकि कोशिकाओं की एक निश्चित चौड़ाई होती है, लेकिन यह अन्य स्थितियों जैसे iPad लेआउट जैसी कई कॉलमों में निश्चित चौड़ाई वाली कोशिकाओं को समायोजित नहीं करेगा।

जवाबों:


135

ऐसा लगता है कि आप जो पूछ रहे हैं, वह UICablelectViewView का उपयोग करने का एक तरीका है, जैसे कि UITableView जैसे लेआउट का उत्पादन करना। अगर यह वास्तव में आप क्या चाहते हैं, तो ऐसा करने का सही तरीका कस्टम UICollectionViewLayout उपवर्ग (शायद SBTableLayout जैसा कुछ ) के साथ है।

दूसरी ओर, यदि आप वास्तव में पूछ रहे हैं कि क्या डिफ़ॉल्ट UICollectionViewFlowLayout के साथ ऐसा करने का कोई साफ तरीका है, तो मेरा मानना ​​है कि कोई रास्ता नहीं है। यहां तक ​​कि iOS8 के सेल्फ-साइजिंग सेल के साथ, यह सीधा नहीं है। मौलिक समस्या, जैसा कि आप कहते हैं, यह है कि प्रवाह लेआउट की मशीनरी एक आयाम को ठीक करने और कोई अन्य प्रतिक्रिया देने का कोई रास्ता नहीं प्रदान करती है। (इसके अलावा, यदि आप कर सकते हैं, तो मल्टी-लाइन लेबल्स को आकार देने के लिए दो लेआउट पास की आवश्यकता के आसपास अतिरिक्त जटिलता होगी। यह स्व-आकार देने वाली कोशिकाओं को एक कॉल के माध्यम से सभी साइलेज को सिस्टमलैटआउटफिटिंगसाइज के साथ गणना करने के तरीके के साथ फिट नहीं हो सकता है।)

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

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

अपने UICollectionViewDelegateFlowLayout में, आप इस तरह से एक विधि लागू करते हैं:

func collectionView(collectionView: UICollectionView,
  layout collectionViewLayout: UICollectionViewLayout,
  sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
  // NOTE: here is where we say we want cells to use the width of the collection view
   let requiredWidth = collectionView.bounds.size.width

   // NOTE: here is where we ask our sizing cell to compute what height it needs
  let targetSize = CGSize(width: requiredWidth, height: 0)
  /// NOTE: populate the sizing cell's contents so it can compute accurately
  self.sizingCell.label.text = items[indexPath.row]
  let adequateSize = self.sizingCell.preferredLayoutSizeFittingSize(targetSize)
  return adequateSize
}

यह संग्रह दृश्य को एन्क्लोज़िंग संग्रह दृश्य के आधार पर सेल की चौड़ाई सेट करने का कारण होगा, लेकिन फिर साइज़िंग सेल से ऊँचाई की गणना करने के लिए कहें।

दूसरा भाग ऊंचाई की गणना करने के लिए अपने स्वयं के AL बाधाओं का उपयोग करने के लिए आकार देने वाला सेल प्राप्त करना है। यह इस तरह से कठिन होना चाहिए, क्योंकि मल्टी-लाइन यूआईबेल के प्रभावी ढंग से दो-चरण लेआउट प्रक्रिया की आवश्यकता होती है। कार्य विधि में किया जाता है preferredLayoutSizeFittingSize, जो इस प्रकार है:

 /*
 Computes the size the cell will need to be to fit within targetSize.

 targetSize should be used to pass in a width.

 the returned size will have the same width, and the height which is
 calculated by Auto Layout so that the contents of the cell (i.e., text in the label)
 can fit within that width.

 */
 func preferredLayoutSizeFittingSize(targetSize:CGSize) -> CGSize {

   // save original frame and preferredMaxLayoutWidth
   let originalFrame = self.frame
   let originalPreferredMaxLayoutWidth = self.label.preferredMaxLayoutWidth

   // assert: targetSize.width has the required width of the cell

   // step1: set the cell.frame to use that width
   var frame = self.frame
   frame.size = targetSize
   self.frame = frame

   // step2: layout the cell
   self.setNeedsLayout()
   self.layoutIfNeeded()
   self.label.preferredMaxLayoutWidth = self.label.bounds.size.width

   // assert: the label's bounds and preferredMaxLayoutWidth are set to the width required by the cell's width

   // step3: compute how tall the cell needs to be

   // this causes the cell to compute the height it needs, which it does by asking the 
   // label what height it needs to wrap within its current bounds (which we just set).
   let computedSize = self.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

   // assert: computedSize has the needed height for the cell

   // Apple: "Only consider the height for cells, because the contentView isn't anchored correctly sometimes."
   let newSize = CGSize(width:targetSize.width,height:computedSize.height)

   // restore old frame and preferredMaxLayoutWidth
   self.frame = originalFrame
   self.label.preferredMaxLayoutWidth = originalPreferredMaxLayoutWidth

   return newSize
 }

(यह कोड "एडवांस्ड कलेक्शन व्यू" पर WWDC2014 सत्र के नमूना कोड से Apple नमूना कोड से अनुकूलित है।)

एक युगल नोटिस की ओर इशारा करता है। यह संपूर्ण सेल के लेआउट को बाध्य करने, लेबल की चौड़ाई की गणना करने और सेट करने के लिए लेआउटआईफाइड () का उपयोग कर रहा है। लेकिन इतना ही काफी नहीं है। मेरा मानना ​​है कि आपको सेट करने की भी आवश्यकता है preferredMaxLayoutWidthताकि लेबल ऑटो लेआउट के साथ उस चौड़ाई का उपयोग करे। और इसके बाद ही आप systemLayoutSizeFittingSizeलेबल को खाते में लेते हुए इसकी ऊंचाई की गणना करने के लिए सेल का उपयोग कर सकते हैं ।

क्या मुझे यह तरीका पसंद है? नहीं!! यह बहुत जटिल लगता है, और यह दो बार लेआउट करता है। लेकिन जब तक प्रदर्शन एक मुद्दा नहीं बन जाता है, मैं रनटाइम में दो बार लेआउट का प्रदर्शन करता हूं, जबकि इसे दो बार कोड में परिभाषित करना पड़ता है, जो केवल अन्य विकल्प लगता है।

मेरी आशा है कि अंततः स्व-आकार देने वाले सेल अलग तरीके से काम करेंगे और यह सब बहुत सरल हो जाएगा।

उदाहरण परियोजना इसे काम पर दिखा रही है।

लेकिन सिर्फ स्व-आकार देने वाली कोशिकाओं का उपयोग क्यों न करें?

सिद्धांत रूप में, "स्व-आकार देने वाली कोशिकाओं" के लिए iOS8 की नई सुविधाओं को यह अनावश्यक बनाना चाहिए। यदि आपने ऑटो लेआउट (AL) के साथ एक सेल को परिभाषित किया है, तो संग्रह दृश्य को स्मार्ट होना चाहिए ताकि वह खुद को आकार दे सके और खुद को सही ढंग से बाहर कर सके। व्यवहार में, मैंने ऐसा कोई उदाहरण नहीं देखा है जिसने मल्टी-लाइन लेबल के साथ काम करने के लिए इसे प्राप्त किया हो। मुझे लगता है कि यह आंशिक रूप से है क्योंकि स्व-साइटिंग सेल तंत्र अभी भी छोटी गाड़ी है।

लेकिन मैं शर्त लगाता हूँ कि यह ज्यादातर ऑटो लेआउट और लेबल की सामान्य चाल के कारण होता है, जो यह है कि UILabels को मूल रूप से दो-चरण लेआउट प्रक्रिया की आवश्यकता होती है। यह मेरे लिए स्पष्ट नहीं है कि आप स्व-आकार देने वाली कोशिकाओं के साथ दोनों चरणों का प्रदर्शन कैसे कर सकते हैं।

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

और क्या पसंद के बारे में

preferredLayoutAttributesFittingAttributes:विधि एक रेड हेरिंग है, मुझे लगता है। यह केवल नए स्व-आकार देने वाले सेल तंत्र के साथ उपयोग किए जाने के लिए है। तो यह जवाब नहीं है क्योंकि यह तंत्र अविश्वसनीय है।

और systemlayoutSizeFittingSize के साथ क्या हो रहा है:?

आप सही हैं कि डॉक्स भ्रमित कर रहे हैं।

डॉक्स ऑन systemLayoutSizeFittingSize:और systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:दोनों यह सुझाव देते हैं कि आपको केवल पास होना चाहिए UILayoutFittingCompressedSizeऔर UILayoutFittingExpandedSizeजैसा होना चाहिए targetSize। हालाँकि, विधि हस्ताक्षर स्वयं, शीर्ष लेख टिप्पणियाँ, और फ़ंक्शन के व्यवहार से संकेत मिलता है कि वे targetSizeपैरामीटर के सटीक मान पर प्रतिक्रिया दे रहे हैं ।

वास्तव में, यदि आप UICollectionViewFlowLayoutDelegate.estimatedItemSizeनए स्व-आकारीय सेल तंत्र को सक्षम करने के लिए सेट करते हैं, तो यह मान लक्षित लक्ष्य के रूप में पारित हो जाता है। और UILabel.systemLayoutSizeFittingSizeजैसा लगता है ठीक वैसा ही मान लौटता है UILabel.sizeThatFits। यह संदेहास्पद है, यह देखते हुए कि तर्क को systemLayoutSizeFittingSizeएक मोटा लक्ष्य sizeThatFits:माना जाता है और तर्क को अधिकतम आकार का आकार माना जाता है।

और अधिक संसाधनों

हालांकि यह सोचना दुखद है कि इस तरह की नियमित आवश्यकता के लिए "शोध संसाधनों" की आवश्यकता होती है, मुझे लगता है कि यह करता है। अच्छे उदाहरण और चर्चाएँ हैं:


आप फ्रेम को पुराने फ्रेम में वापस क्यों सेट करते हैं?
vrwim

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

1
यह किसी चीज के लिए ऐसी गड़बड़ी है जो लोग ios6 के बाद से कर रहे हैं। Apple हमेशा किसी न किसी तरह से निकलता है लेकिन यह कभी भी सही नहीं होता है।
ग्रेग

1
आप मैन्युअल रूप से साइज़िंग सेल को viewDidLoad में इंस्टेंट कर सकते हैं और उसमें एक कस्टम प्रॉपर्टी देख सकते हैं। यह केवल एक सेल है इसलिए यह सस्ता है। चूंकि आप इसे केवल आकार देने के लिए उपयोग कर रहे हैं, और आप इसके साथ सभी सहभागिता का प्रबंधन कर रहे हैं, इसलिए इसे संग्रह दृश्य के सेल पुन: उपयोग तंत्र में भाग लेने की आवश्यकता नहीं है, इसलिए आपको इसे संग्रह दृश्य से प्राप्त करने की आवश्यकता नहीं है।
शैवाल

1
कैसे पृथ्वी पर आत्म-आकार देने वाली कोशिकाओं को अभी भी तोड़ा जा सकता है ?!
रूबेन स्क्रैटन

50

यहां कुछ अन्य उत्तरों की तुलना में ऐसा करने का एक क्लीनर तरीका है, और यह अच्छी तरह से काम करता है। यह प्रदर्शनकारी होना चाहिए (संग्रह के दृश्य तेजी से लोड होते हैं, कोई अनावश्यक ऑटो लेआउट पास नहीं होता है), और निश्चित संग्रह चौड़ाई की तरह कोई 'मैजिक नंबर' नहीं है। संग्रह के आकार को बदलना, जैसे रोटेशन पर, और फिर लेआउट को अमान्य करना भी बहुत अच्छा काम करना चाहिए।

1. निम्न प्रवाह लेआउट उपवर्ग बनाएँ

class HorizontallyFlushCollectionViewFlowLayout: UICollectionViewFlowLayout {

    // Don't forget to use this class in your storyboard (or code, .xib etc)

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
        let attributes = super.layoutAttributesForItemAtIndexPath(indexPath)?.copy() as? UICollectionViewLayoutAttributes
        guard let collectionView = collectionView else { return attributes }
        attributes?.bounds.size.width = collectionView.bounds.width - sectionInset.left - sectionInset.right
        return attributes
    }

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let allAttributes = super.layoutAttributesForElementsInRect(rect)
        return allAttributes?.flatMap { attributes in
            switch attributes.representedElementCategory {
            case .Cell: return layoutAttributesForItemAtIndexPath(attributes.indexPath)
            default: return attributes
            }
        }
    }
}

2. स्वत: आकार देने के लिए अपना संग्रह दृश्य पंजीकृत करें

// The provided size should be a plausible estimate of the actual
// size. You can set your item size in your storyboard
// to a good estimate and use the code below. Otherwise,
// you can provide it manually too, e.g. CGSize(width: 100, height: 100)

flowLayout.estimatedItemSize = flowLayout.itemSize

3. अपने सेल उपवर्ग में पूर्वनिर्धारित चौड़ाई + कस्टम ऊंचाई का उपयोग करें

override func preferredLayoutAttributesFittingAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    layoutAttributes.bounds.size.height = systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
    return layoutAttributes
}

8
यह सबसे बड़ा जवाब है जो मैंने आत्म-आकार देने वाले विषय पर पाया है। शुक्रिया जॉर्डन!
haik.ampardjian

1
IOS (9.3) पर काम करने के लिए इसे प्राप्त नहीं कर सकते। 10 पर यह ठीक काम करता है। अनुप्रयोग _updateVanishCells (अनंत पुनरावर्तन?) पर क्रैश हो जाता है। Openradar.me/25303115
cristiano2lope

@ cristiano2lope यह मेरे लिए iOS 9.3 पर अच्छा काम करता है। सुनिश्चित करें कि आप एक उचित अनुमान प्रदान कर रहे हैं, और सुनिश्चित करें कि एक सही आकार का समाधान करने के लिए आपके सेल अवरोध स्थापित किए गए हैं।
जॉर्डन स्मिथ

यह अद्भुत काम करता है। मैं Xcode 8 का उपयोग कर रहा हूं और iOS 9.3.3 (भौतिक डिवाइस) में परीक्षण किया गया है और यह क्रैश नहीं होता है! बहुत अच्छा काम करता है। बस सुनिश्चित करें कि आपका अनुमान अच्छा है!
हाहाकार

1
@JordanSmith यह iOS 10 में काम नहीं कर रहा है। क्या आपके पास कोई सैंपल डेमो है। मैंने अपनी सामग्री के आधार पर संग्रह दृश्य सेल ऊंचाई करने के लिए बहुत सी चीजों की कोशिश की है, लेकिन कुछ भी नहीं। मैं iOS 10 में ऑटो लेआउट का उपयोग कर रहा हूं और स्विफ्ट 3 का उपयोग कर रहा हूं।
एकता पडलिया

6

IOS 9 में इसे कोड की कुछ पंक्तियों में करने का एक सरल तरीका है - क्षैतिज तरीके से छूट (इसकी ऊँचाई को इसके संग्रह की ऊँचाई तक फिक्स करना):

estimatedItemSizeसेल्फ-साइज़िंग सेल को सक्षम करने के लिए अपने कलेक्शन व्यू फ्लो लेआउट को सम्मिलित करें :

self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.estimatedItemSize = CGSizeMake(1, 1);

संग्रह दृश्य लेआउट डेलिगेट को लागू करें (अपने दृश्य नियंत्रक में अधिकांश समय) collectionView:layout:sizeForItemAtIndexPath:,। यहां लक्ष्य संग्रह दृश्य आयाम के लिए निश्चित ऊंचाई (या चौड़ाई) निर्धारित करना है। 10 मान कुछ भी हो सकता है, लेकिन आपको इसे ऐसे मूल्य पर सेट करना चाहिए जो बाधाओं को नहीं तोड़ता है:

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(10, CGRectGetHeight(collectionView.bounds));
}

अपनी कस्टम सेल preferredLayoutAttributesFittingAttributes:विधि को ओवरराइड करें , यह हिस्सा वास्तव में आपके ऑटो लेआउट की कमी और आपके द्वारा निर्धारित ऊंचाई के आधार पर आपके डायनामिक सेल की चौड़ाई की गणना करता है:

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
{
    UICollectionViewLayoutAttributes *attributes = [layoutAttributes copy];
    float desiredWidth = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].width;
    CGRect frame = attributes.frame;
    frame.size.width = desiredWidth;
    attributes.frame = frame;
    return attributes;
}

क्या आप जानते हैं कि iOS9 पर यह सरल विधि सही ढंग से काम करती है जब सेल में एक मल्टी-लाइन शामिल होती है UILabel, जिसका लाइन-ब्रेकिंग सेल की आंतरिक ऊंचाई को प्रभावित करता है? यह एक सामान्य मामला है जिसका उपयोग मुझे बताए गए सभी बैकफ्लिप्स की आवश्यकता होती है। मैं सोच रहा था कि क्या मेरे जवाब के बाद से iOS ने इसे ठीक किया है।
एलिगॉन

2
@गाल दुःख की बात है कि इसका जवाब नहीं है।
६:६६ पर जम्स्क

4

पसंदीदा लेआउट विशेषताओं में अपनी चौड़ाई तय करने का प्रयास करें:

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    UICollectionViewLayoutAttributes *attributes = [[super preferredLayoutAttributesFittingAttributes:layoutAttributes] copy];
    CGSize newSize = [self systemLayoutSizeFittingSize:CGSizeMake(FIXED_WIDTH,layoutAttributes.size) withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel];
    CGRect newFrame = attr.frame;
    newFrame.size.height = size.height;
    attr.frame = newFrame;
    return attr;
}

स्वाभाविक रूप से आप यह भी सुनिश्चित करना चाहते हैं कि आप अपने लेआउट को सही तरीके से सेट करें:

UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *) self.collectionView.collectionViewLayout;
flowLayout.estimatedItemSize = CGSizeMake(FIXED_WIDTH, estimatedHeight)];

हेथ्स कुछ मैं गितुब पर डालता हूं जो निरंतर चौड़ाई की कोशिकाओं का उपयोग करता है और गतिशील प्रकार का समर्थन करता है ताकि कोशिकाओं की ऊंचाई सिस्टम फ़ॉन्ट आकार में परिवर्तन के रूप में अपडेट हो।


इस स्निपेट में आप systemLayoutSizeFittingSize: कहते हैं। क्या आपने इसे प्राथमिकता के बिना काम करने में कामयाब कर दिया है। मेरे अनुभव में, यदि आप अधिमानतः मैक्लैटआउट की स्थापना नहीं कर रहे हैं, तो आपको अतिरिक्त मैनुअल लेआउट करने की आवश्यकता है, उदाहरण के लिए, आकार को हटाकर।
अल्गल

@algal पसंदीदामैक्स लाईटविथ UILabel पर एक संपत्ति है? पूरी तरह से सुनिश्चित नहीं है कि यह प्रासंगिक कैसे है?
बजे डैनियल गैलास्को

ऊप्स! अच्छी बात है, यह नहीं है! मैंने इसे UITextView के साथ कभी भी संभाला नहीं है, इसलिए यह महसूस नहीं किया कि उनके एपीआई वहाँ भिन्न थे। UITextView.systemLayoutSizeFittingSize की तरह लगता है इसका फ्रेम का सम्मान करता है क्योंकि इसमें कोई आंतरिक नियंत्रण नहीं है। लेकिन UILabel.systemLayoutSizeFittingSize फ्रेम को अनदेखा कर देता है, क्योंकि इसमें एक आंतरिक आंतरिकता है, इसलिए AL के लिए अपनी लिपटे हुए ऊँचाई को उजागर करने के लिए intrinsicContentisize प्राप्त करने के लिए पसंदीदाMaxLayoutWidth की आवश्यकता होती है। अभी भी ऐसा लगता है कि UITextView को दो पास या मैनुअल लेआउट की आवश्यकता होगी, लेकिन मुझे नहीं लगता कि मैं इसे पूरी तरह से समझता हूं।
अल्गल

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

0

YES इसे प्रोग्राम लेआउट या xib में बाधाओं को सेट करके प्रोग्रामेटिक रूप से ऑटो लेआउट का उपयोग करके किया जा सकता है। आपको स्थिर रहने के लिए चौड़ाई के आकार में बाधा जोड़ने और ऊंचाई को बराबर या उससे अधिक करने की आवश्यकता है।
http://www.thinkandbuild.it/learn-to-love-auto-layout-programmatically/

http://www.cocoanetics.com/2013/08/variable-sized-items-in-uicollectionview/
उम्मीद है कि यह होगा मददगार और अपने मुद्दे को हल।


3
यह निरपेक्ष चौड़ाई मान के लिए काम करना चाहिए, लेकिन यदि आप चाहते हैं कि सेल हमेशा संग्रह दृश्य की पूरी चौड़ाई हो, तो यह काम नहीं करेगा।
माइकल वाटरफॉल

@MichaelWaterfall मैं इसे AutoLayout का उपयोग करके पूरी चौड़ाई के साथ काम करने में कामयाब रहा। मैंने सेल के अंदर अपने कंटेंट दृश्य पर एक चौड़ाई की बाधा जोड़ी है। फिर cellForItemAtIndexPathबाधा को अद्यतन करने में cell.constraintItemWidth.constant = UIScreen.main.bounds.width:। मेरा ऐप पोर्टेट-ओनली है। आप शायद reloadDataबाधा को अद्यतन करने के लिए एक अभिविन्यास परिवर्तन के बाद चाहते हैं ।
फ्लिट्सकीकर 11
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.