UITollectionView एक UITableViewCell के अंदर - गतिशील ऊंचाई?


125

हमारे एप्लिकेशन स्क्रीन में से एक को हमें UICollectionViewअंदर रखने की आवश्यकता होती है UITableViewCell। इसमें UICollectionViewवस्तुओं की एक गतिशील संख्या होगी, जिसके परिणामस्वरूप एक ऊँचाई होगी जिसे गतिशील रूप से भी गणना की जानी चाहिए। हालांकि, मैं एम्बेडेड की ऊंचाई की गणना करने की कोशिश कर रही समस्याओं में भाग रहा हूं UICollectionView

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

क्या कोई इसे पूरा करने के लिए कुछ सुझाव या सलाह दे सकता है?


क्या आप उस लेआउट के बारे में थोड़ा और बता सकते हैं जिसे आप पूरा करने की कोशिश कर रहे हैं? क्या UITableViewCellइसकी एक्यूट टेबलव्यू से अलग की ऊंचाई है ? आप दोनों पर खड़ी स्क्रॉल की जरूरत है UICollectionViewऔरUITableView
apouche

3
UITableViewCell की ऊँचाई को डायनेमिक माना जाता है, जो UICollectionView की ऊँचाई के आधार पर तालिका व्यू सेल का हिस्सा है। मेरे UICollectionView का लेआउट 4 कॉलम और पंक्तियों की एक गतिशील संख्या है। तो, 100 आइटम के साथ, मेरे UICollectionView में 4 कॉलम और 25 पंक्तियाँ होंगी। विशेष सेल की ऊंचाई - जैसा कि यूआईटेबल व्यू की ऊँचाई से दर्शाया गया है फ़ोरराउटइंडेक्सपैथ - को उस यूआईसीओलेक्शनियन व्यू के आकार के आधार पर समायोजित करने में सक्षम होना चाहिए। क्या यह थोड़ा और स्पष्ट है?
शैडोमैन

@ शादोमन, कृपया मुझे इस स्थिति के लिए एक उपाय सुझाएं
रवि ओझा

जवाबों:


127

सही उत्तर हां है , आप ऐसा कर सकते हैं।

मुझे इस समस्या के बारे में कुछ हफ्ते पहले आया था। यह वास्तव में आसान है जितना आप सोच सकते हैं। अपनी कोशिकाओं को एनआईबी (या स्टोरीबोर्ड) में डालें और ऑटो लेआउट को सभी काम करने देने के लिए उन्हें पिन करें

निम्नलिखित संरचना को देखते हुए:

tableview

TableViewCell

CollectionView

CollectionViewCell

CollectionViewCell

CollectionViewCell

[... कोशिकाओं या विभिन्न सेल आकारों की परिवर्तनशील संख्या]

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

-(void)systemLayoutSizeFittingSize:(CGSize)targetSize 
     withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority 
           verticalFittingPriority:(UILayoutPriority)verticalFittingPriority

आपको यहां TableViewCell का आकार सेट करना होगा, जो आपके मामले में CollectionView की सामग्री है।

CollectionViewCell

पर CollectionViewCell आप हर बार जब आप मॉडल बदलने लेआउट करने के लिए सेल बताने के लिए है (उदाहरण के लिए: यदि आप एक पाठ के साथ एक UILabel निर्धारित करते हैं, तो सेल फिर से लेआउट हो गया है)।

- (void)bindWithModel:(id)model {
    // Do whatever you may need to bind with your data and 
    // tell the collection view cell's contentView to resize
    [self.contentView setNeedsLayout];
}
// Other stuff here...

TableViewCell

TableViewCell जादू करता है। इसमें आपके संग्रह दृश्य के लिए एक आउटलेट है, UICollectionViewFlowLayout के अनुमानित Itememize का उपयोग करके संग्रह दृश्य कोशिकाओं के लिए ऑटो लेआउट को सक्षम करता है ।

फिर, ट्रिक को अपने टेबल व्यू सेल के आकार को systemLayoutSizeFittingSize ... विधि पर सेट करना है । (नोट: iOS8 या बाद में)

नोट: मैंने डेलिगेट सेल के टेबल व्यू की ऊंचाई विधि का उपयोग करने की कोशिश की है। -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPathलेकिन यह संग्रह लेआउट सामग्री की गणना करने के लिए ऑटो लेआउट सिस्टम के लिए बहुत देर हो चुकी है और कभी-कभी आपको गलत रिसाइज्ड सेल मिल सकती हैं।

@implementation TableCell

- (void)awakeFromNib {
    [super awakeFromNib];
    UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;

    // Configure the collectionView
    flow.minimumInteritemSpacing = ...;

    // This enables the magic of auto layout. 
    // Setting estimatedItemSize different to CGSizeZero 
    // on flow Layout enables auto layout for collectionView cells.
    // https://developer.apple.com/videos/play/wwdc2014-226/
    flow.estimatedItemSize = CGSizeMake(1, 1);

    // Disable the scroll on your collection view
    // to avoid running into multiple scroll issues.
    [self.collectionView setScrollEnabled:NO];
}

- (void)bindWithModel:(id)model {
    // Do your stuff here to configure the tableViewCell
    // Tell the cell to redraw its contentView        
    [self.contentView layoutIfNeeded];
}

// THIS IS THE MOST IMPORTANT METHOD
//
// This method tells the auto layout
// You cannot calculate the collectionView content size in any other place, 
// because you run into race condition issues.
// NOTE: Works for iOS 8 or later
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority {

    // With autolayout enabled on collection view's cells we need to force a collection view relayout with the shown size (width)
    self.collectionView.frame = CGRectMake(0, 0, targetSize.width, MAXFLOAT);
    [self.collectionView layoutIfNeeded];

    // If the cell's size has to be exactly the content 
    // Size of the collection View, just return the
    // collectionViewLayout's collectionViewContentSize.

    return [self.collectionView.collectionViewLayout collectionViewContentSize];
}

// Other stuff here...

@end

TableViewController

अपने TableViewController पर तालिका दृश्य कोशिकाओं के लिए ऑटो लेआउट सिस्टम को सक्षम करने के लिए याद रखें :

- (void)viewDidLoad {
    [super viewDidLoad];

    // Enable automatic row auto layout calculations        
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    // Set the estimatedRowHeight to a non-0 value to enable auto layout.
    self.tableView.estimatedRowHeight = 10;

}

CREDIT: @rbarbera ने इसे सुलझाने में मदद की


4
हाँ। यह काम। यह स्वीकृत उत्तर होना चाहिए।
csotiriou

1
क्या कोई निकाय मुझे इसके लिए एक नमूना कोड प्रदान कर सकता है? मैं कई चित्रों को वर्टिकल कलेक्शन व्यू में दिखाना चाहता हूं, जो कि टेबलव्यू सेल के अंदर हैं ..
रवि ओझा

4
अंत में यह मेरे लिए काम कर रहा है, लेकिन मुझे एक और चाल करनी थी: cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);यह एक लंबे संग्रह के साथ एक लंबी सेल को "अनुकरण" करेगा, इसलिए संग्रह दृश्य इसकी सभी कोशिकाओं के आकार की गणना करेगा। अन्यथा संग्रह दृश्य केवल दृश्यमान सेल आकार की गणना करता है, और गलत तरीके से talbeViewCell ऊंचाई सेट करता है।
इंगहैम

20
जब फ्रेम की ऊँचाई अधिकतम करने के लिए सेट की जाती है systemLayoutSizeFittingSize, तो मैं सेल को पुनः लोड करते समय तेज़ी से एक समस्या से टकराता हूँ, लगता है कि ऐप्स इसके बाद अटक गए हैं self.collectionView.layoutIfNeeded()। मैंने इसे अधिकतम ऊंचाई के बजाय 1 के साथ फ्रेम की ऊंचाई निर्धारित करके तय किया। आशा है कि अगर किसी को भी इस समस्या में ठोकर खाने में मदद मिलती है।
टाइटन

6
यहाँ मेरे लिए यह निर्धारित किया गया है - systemLayoutSizeFittingवर्तमान में उत्तर में दिखाए गए के क्रम को उल्टा कर दें, ताकि पहले collectionView.layoutIfNeeded()भाग जाए, फिरcollectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
xaphod

101

मुझे लगता है कि मेरा समाधान @PabloRomeu द्वारा प्रस्तावित की तुलना में बहुत सरल है।

चरण 1 से आउटलेट बनाएं UICollectionViewकरने के लिए UITableViewCell subclassहै, जहां UICollectionViewरखा गया है। चलो, यह नाम होगाcollectionView

चरण 2. UICollectionViewऊंचाई की कमी के लिए आईबी में जोड़ें और UITableViewCell subclassभी आउटलेट बनाएं । चलो, यह नाम होगा collectionViewHeight

चरण 3. tableView:cellForRowAtIndexPath:ऐड कोड में:

// deque a cell
cell.frame = tableView.bounds;
[cell layoutIfNeeded];
[cell.collectionView reloadData];
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height;

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

2
मैंने यह काम किया है। मैं collectionViewसभी पक्षों के लिए बाधाओं को जोड़ता हूं UITableViewCellऔर सेट करता हूं tableView.estimatedRowHeight = 44;औरtableView.rowHeight = UITableViewAutomaticDimension;
इगोर

3
यह शैंपू की तरह काम करता है ... सरल और कुशल ... धन्यवाद। यदि किसी के लिए यह काम नहीं कर रहा है तो शायद इसका कारण हो सकता है, हमें संग्रह दृश्य के निचले भाग को टेबल व्यू सेल के नीचे से बांधना होगा। फिर यह काम करना शुरू कर देगा। हैप्पी कोडिंग .. :)
सेबीन रॉय

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

2
क्या आपने विभिन्न संग्रह दृश्य सेल के आकार आज़माए हैं? यही मेरी समस्या थी। यदि आपके पास अलग-अलग कलेक्शन व्यू के सेल साइज हैं तो यह काम नहीं करता ... :(
पाब्लो रोमू

22

तालिका दृश्य और संग्रह दृश्य दोनों UIScrollViewउपवर्ग हैं और इस प्रकार एक और स्क्रॉल दृश्य के अंदर एम्बेड किया जाना पसंद नहीं है क्योंकि वे सामग्री आकार, पुन: उपयोग कोशिकाओं आदि की गणना करने का प्रयास करते हैं।

मैं आपको अपने सभी उद्देश्यों के लिए केवल एक संग्रह दृश्य का उपयोग करने की सलाह देता हूं।

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

यदि आपके पास अपने संग्रह दृश्य "भागों" के लिए एक बुनियादी ग्रिड लेआउट है, तो आप उन्हें संभालने के लिए नियमित टेबल कोशिकाओं का भी उपयोग कर सकते हैं। फिर भी अगर आपको iOS 5 सपोर्ट की जरूरत नहीं है तो आपको कलेक्शन व्यू का बेहतर इस्तेमाल करना चाहिए।


1
आपने उद्धरणों में "ट्रीट" डाला है, क्योंकि आप प्रति संग्रह व्यू अनुभाग में अलग-अलग लेआउट को परिभाषित नहीं कर सकते हैं, है ना? मुझे विभिन्न संग्रह दृश्य अनुभागों के लिए विभिन्न लेआउट को परिभाषित करने का विकल्प नहीं मिला है। क्या मैं कुछ अनदेखी कर रहा हूं या आप UICollectionViewLayout के अपने कस्टम उपवर्ग में अलग-अलग वर्गों के लिए 'LayoutAttributesForItemAtIndexPath' के लिए अलग-अलग जवाब देने की बात कर रहे हैं?
एलेक्स दा फ्रैंका

हां -> क्या आप layoutAttributesForItemAtIndexPathअपने स्वयं के कस्टम उपवर्ग में विभिन्न वर्गों के लिए अलग- अलग जवाब देने की बात कर रहे हैं UICollectionViewLayout?
रिवेरा

2
@ रीवर, आपका जवाब सबसे उचित है और सही लगता है। मैंने कई जगहों पर इस सुझाव को पढ़ा है। क्या आप नमूना या ट्यूट पर कुछ लिंक साझा कर सकते हैं कि कैसे या कम से कम कुछ संकेत को पूरा करने के लिए। टीआईए
thesummersign

3
आपका उत्तर मानता है कि आप स्क्रैच से शुरू कर रहे हैं, और पहले से ही एक बड़ा जटिल टेबलव्यू नहीं है जिसे आपको फिट करने की आवश्यकता है। विशेष रूप से एक टेबलव्यू में कलेक्शनव्यू डालने के बारे में पूछा गया प्रश्न। IMO आपकी प्रतिक्रिया "उत्तर" नहीं है
xaphod

2
यह एक बुरा जवाब है। टेबल व्यू के अंदर कलेक्शन व्यूज का ऐसा होना एक आम बात है, लगभग हर ऐप ऐसा करता है।
crashoverride777

10

पाब्लो रोमू के उत्तर के ऊपर ( https://stackoverflow.com/a/33364092/2704206 ) ने मुझे अपने मुद्दे पर बहुत मदद की। मुझे अपनी समस्या के लिए यह काम करने के लिए अलग से कुछ चीजें करनी थीं। सबसे पहले, मुझे layoutIfNeeded()अक्सर कॉल नहीं करना पड़ा । मुझे इसे फंक्शन collectionViewमें बुलाना था systemLayoutSizeFitting

दूसरे, मेरे पास टेबल व्यू सेल में मेरे संग्रह दृश्य पर ऑटो लेआउट की कमी थी, इसलिए इसे कुछ पैडिंग देने के लिए। इसलिए मुझे प्रमुख और अनुगामी मार्जिन को घटाना है, targetSize.widthजब इसकी collectionView.frameचौड़ाई निर्धारित की गई थी । मुझे रिटर्न वैल्यू CGSizeऊँचाई पर शीर्ष और निचले मार्जिन को भी जोड़ना था ।

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

class CollectionTableViewCell: UITableViewCell {

    // MARK: -
    // MARK: Properties
    @IBOutlet weak var collectionView: UICollectionView! {
        didSet {
            collectionViewLayout?.estimatedItemSize = CGSize(width: 1, height: 1)
            selectionStyle = .none
        }
    }

    var collectionViewLayout: UICollectionViewFlowLayout? {
        return collectionView.collectionViewLayout as? UICollectionViewFlowLayout
    }

    // MARK: -
    // MARK: UIView functions
    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()

        let topConstraintConstant = contentView.constraint(byIdentifier: "topAnchor")?.constant ?? 0
        let bottomConstraintConstant = contentView.constraint(byIdentifier: "bottomAnchor")?.constant ?? 0
        let trailingConstraintConstant = contentView.constraint(byIdentifier: "trailingAnchor")?.constant ?? 0
        let leadingConstraintConstant = contentView.constraint(byIdentifier: "leadingAnchor")?.constant ?? 0

        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width - trailingConstraintConstant - leadingConstraintConstant, height: 1)

        let size = collectionView.collectionViewLayout.collectionViewContentSize
        let newSize = CGSize(width: size.width, height: size.height + topConstraintConstant + bottomConstraintConstant)
        return newSize
    }
}

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

extension UIView {
    func constraint(byIdentifier identifier: String) -> NSLayoutConstraint? {
        return constraints.first(where: { $0.identifier == identifier })
    }
}

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

ऊपर दी गई कस्टम टेबल व्यू सेल के साथ, मैं अब इसे किसी भी अन्य टेबल व्यू सेल में सबक्लास कर सकता हूं, जिसे कलेक्शन व्यू की जरूरत होती है UICollectionViewDelegateFlowLayoutऔर इसमें UICollectionViewDataSourceप्रोटोकॉल और प्रोटोकॉल लागू होते हैं । आशा है कि यह किसी और के लिए उपयोगी है!


5

मैं सभी उत्तरों के माध्यम से पढ़ता हूं। यह सभी मामलों को पूरा करने के लिए लगता है।

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()
        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width , height: 1)
        return collectionView.collectionViewLayout.collectionViewContentSize
}

3

पाब्लो रोमू के समाधान का एक विकल्प टेबल व्यू सेल में काम करने के बजाय UICollectionView को स्वयं अनुकूलित करना है।

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

UICollectionView का एक उपवर्ग बनाएँ और निम्नलिखित विधियों को ओवरराइड करें

override func intrinsicContentSize() -> CGSize {
    self.layoutIfNeeded()

    var size = super.contentSize
    if size.width == 0 || size.height == 0 {
        // return a default size
        size = CGSize(width: 600, height:44)
    }

    return size
 }

override func reloadData() {
    super.reloadData()
    self.layoutIfNeeded()
    self.invalidateIntrinsicContentSize()
}

(आपको संबंधित विधियों को भी ओवरराइड करना चाहिए: पुनः लोड करें, पुनः लोड करें। AAndexPaths पुनः लोड करने के लिए इसी तरह से ())

कॉलिंग LayoutIfNeeded संग्रह दृश्य को सामग्री के आकार को पुनर्गठित करने के लिए मजबूर करता है जिसे तब नए आंतरिक आकार के रूप में उपयोग किया जा सकता है।

साथ ही, आपको तालिका दृश्य नियंत्रक में दृश्य आकार (जैसे डिवाइस रोटेशन पर) में परिवर्तनों को स्पष्ट रूप से संभालने की आवश्यकता है

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
}

भाई क्या आप कृपया मेरी समस्या stackoverflow.com/questions/44650058/… में मदद कर सकते हैं ?
मई फयू

3

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

में cellForRow:atIndexPathतालिका दृश्य की मैं निम्न कार्य करें:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //do dequeue stuff
    //initialize the the collection view data source with the data
    cell.frame = CGRect.zero
    cell.layoutIfNeeded()
    return cell
}

मुझे लगता है कि यहां क्या होता है कि मैं संग्रह दृश्य ऊंचाई की गणना के बाद टेबलव्यू सेल को अपनी ऊंचाई को समायोजित करने के लिए मजबूर करता हूं। (डेटा स्रोत को संग्रह दृश्य दिनांक प्रदान करने के बाद)


2

मैं संग्रह दृश्य वर्ग पर एक स्थिर विधि लगाऊंगा जो उस सामग्री के आधार पर एक आकार लौटाएगा। फिर heightForRowAtIndexPathउचित आकार वापस करने के लिए उस विधि का उपयोग करें ।

यह भी ध्यान दें कि जब आप इस तरह के व्यू-कॉन्ट्रॉलर्स को एम्बेड करते हैं तो आप कुछ अजीब व्यवहार कर सकते हैं। मैंने इसे एक बार किया था और कुछ अजीब स्मृति मुद्दों पर मैंने कभी काम नहीं किया।


मेरे लिए, मैं संग्रह दृश्य नियंत्रकों के अंदर एक टेबल व्यू कंट्रोलर को एम्बेड करने की कोशिश कर रहा था। हर बार जब एक सेल का दोबारा इस्तेमाल किया जाता है, तो यह खत्म हो जाता है कि मैंने उन पर लगाए गए कुछ ऑटोलैयट बाधाओं को याद किया। यह बहुत ही काल्पनिक था और अंततः एक भयानक विचार था। मुझे लगता है कि मैं इसके बजाय केवल एक संग्रह दृश्य का उपयोग करूंगा।
फतहोकू

2

शायद मेरा संस्करण उपयोगी होगा; मैं पिछले दो घंटों के दौरान इस कार्य को तय कर रहा हूं। मैं यह दिखावा नहीं करता कि यह 100% सही है या इष्टतम है, लेकिन मेरा कौशल अभी बहुत छोटा है और मैं विशेषज्ञों से टिप्पणियां सुनना चाहता हूं। धन्यवाद। एक महत्वपूर्ण नोट: यह स्थैतिक तालिका के लिए काम करता है - यह मेरे वर्तमान कार्य द्वारा निर्दिष्ट है। इसलिए, मेरे द्वारा उपयोग किया जाने वाला सभी व्यू टेबल के व्यू- ऑफ- व्यू साक्षात्कार हैं । और थोड़ा सा और।

private var iconsCellHeight: CGFloat = 500 

func updateTable(table: UITableView, withDuration duration: NSTimeInterval) {
    UIView.animateWithDuration(duration, animations: { () -> Void in
        table.beginUpdates()
        table.endUpdates()
    })
}

override func viewWillLayoutSubviews() {
    if let iconsCell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 1)) as? CategoryCardIconsCell {
        let collectionViewContentHeight = iconsCell.iconsCollectionView.contentSize.height
        if collectionViewContentHeight + 17 != iconsCellHeight {
            iconsCellHeight = collectionViewContentHeight + 17
            updateTable(tableView, withDuration: 0.2)
        }
    }
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch (indexPath.section, indexPath.row) {
        case ...
        case (1,0):
            return iconsCellHeight
        default:
            return tableView.rowHeight
    }
}
  1. मुझे पता है, कि संग्रह दृश्य दूसरे खंड की पहली पंक्ति में स्थित है;
  2. बता दें कि पंक्ति की ऊंचाई 17 पी है। बड़ा, इसकी सामग्री ऊंचाई से;
  3. iconsCellHeight एक यादृच्छिक संख्या है जैसा कि कार्यक्रम शुरू होता है (मुझे पता है, कि चित्र रूप में यह वास्तव में 392 होना चाहिए, लेकिन यह महत्वपूर्ण नहीं है)। यदि संग्रह दृश्य + 17 की सामग्री इस संख्या के बराबर नहीं है, तो इसका मान बदलें। अगली बार इस स्थिति में स्थिति FALSE देती है;
  4. आखिरकार टेबल व्यू को अपडेट करें। मेरे मामले में इसके दो संचालन (विस्तारित पंक्तियों के अच्छे अद्यतन के लिए) का संयोजन;
  5. और हां, ऊँचाई मेंForRowAtIndexPath कोड में एक पंक्ति जोड़ें।

2

अब तक के सबसे बड़े दृष्टिकोण के साथ, ऊपर दिए गए @ मेहनत जवाब का श्रेय,

अपने टेबलव्यू क्लास में बस यही डालें

override func layoutSubviews() {
    self.collectionViewOutlet.constant = self.postPoll.collectionViewLayout.collectionViewContentSize.height
}

और निश्चित रूप से, सेल के वर्ग में अपने आउटलेट के साथ संग्रह दृश्य को बदल दें


1
सेल की ऊँचाई ठीक से गणना नहीं करती है
निक कोव

2

मुझे @Igor पोस्ट से आइडिया मिलता है और अपना समय अपने प्रोजेक्ट के लिए तेजी के साथ लगाता हूं

बस अपने में यह अतीत

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //do dequeue stuff
    cell.frame = tableView.bounds
    cell.layoutIfNeeded()
    cell.collectionView.reloadData()
    cell.collectionView.heightAnchor.constraint(equalToConstant: cell.collectionView.collectionViewLayout.collectionViewContentSize.height)
    cell.layoutIfNeeded()
    return cell
}

जोड़: यदि आप अपना UICollectionView चॉप को लोड करते समय देखते हैं।

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {       
  //do dequeue stuff
  cell.layer.shouldRasterize = true
  cell.layer.rasterizationScale = UIScreen.main.scale
  return cell
}

0

पाब्लो का समाधान मेरे लिए बहुत अच्छा काम नहीं करता था, मेरे पास अजीब दृश्य प्रभाव थे (संग्रह दृश्य सही तरीके से समायोजित नहीं हो रहा था)।

जो काम किया गया था वह संग्रह दृश्य की ऊँचाई की बाधा को समायोजित करना था (NSLayoutConstraint के रूप में) संग्रह के दौरान सामग्री को देखें layoutSubviews()। यह वह विधि है जिसे कोशिका में ऑटोलयूट लागू किया जाता है।

// Constraint on the collectionView height in the storyboard. Priority set to 999.
@IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!


// Method called by autolayout to layout the subviews (including the collectionView).
// This is triggered with 'layoutIfNeeded()', or by the viewController
// (happens between 'viewWillLayoutSubviews()' and 'viewDidLayoutSubviews()'.
override func layoutSubviews() {

    collectionViewHeightConstraint.constant = collectionView.contentSize.height
    super.layoutSubviews()
}

// Call `layoutIfNeeded()` when you update your UI from the model to trigger 'layoutSubviews()'
private func updateUI() {
    layoutIfNeeded()
}

-3

आपके UITableViewDelegate में:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return ceil(itemCount/4.0f)*collectionViewCellHeight;
}

वास्तविक मूल्यों के साथ ItemCount और CollectionViewCellHeight को प्रतिस्थापित करें। यदि आपके पास सरणियों का एक सरणी है तो आइटम हो सकता है:

self.items[indexPath.row].count

जो कुछ भी।


मुझे लगता है कि मुख्य प्रश्न यह है कि गणना करने collectionViewCellHeight से पहले कैसे गणना की जाए।
थिसुमर्सिन

-3

1. बनाएँ डमी सेल।
वर्तमान डेटा का उपयोग करके UICollectionView के UICollectionViewLayout पर 2.Use collectionViewContentSize विधि।


इसका सबसे अच्छा उत्तर होना चाहिए ... क्योंकि डमी सेल में सामग्री डालने के बिना 'यूकोलक्लिओनव्यू' के साथ सेल की ऊंचाई निर्धारित करने की कोई संभावना नहीं है, ऊंचाई प्राप्त करें, और फिर इसे फिर से उचित सेल पर सेट करें
बार्टोलोमिएज सेसकोज़िक

मैं उस विधि का उपयोग कैसे करूं?
xtrinch

एक उदाहरण जोड़ें।
निक कोव

-5

आप की तरह अपने गुणों के आधार पर संग्रह की ऊंचाई की गणना कर सकते itemSize, sectionInset, minimumLineSpacing, minimumInteritemSpacing, अपने यदि collectionViewCellएक नियम की सीमा है।

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