विभिन्न डिवाइस ओरिएंटेशन पर UICollectionViewCell आकार बदलें


100

मैं एक के UICollectionViewसाथ प्रयोग कर रहा हूँ UICollectionViewFlowLayout

मैं के माध्यम से प्रत्येक कोशिका का आकार निर्धारित करता हूं

collectionView:layout:sizeForItemAtIndexPath:

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

प्रशन:

1) रोटेशन इवेंट के बाद सेल का आकार कैसे बदलें?

2) और, और भी बेहतर, लेआउट कैसे बनाएं जहां कोशिकाएं हमेशा स्क्रीन के पूरे आकार में फिट होती हैं?


फॉलोबेन के उत्तर को वर्तमान में स्वीकार कर लिया गया है, लेकिन इसके कुछ मुद्दे हैं: यह एक कंसोल एरर को फेंक देगा और नए आकार के लिए एनीमेशन सही ढंग से नहीं होगा। सही कार्यान्वयन के लिए मेरा जवाब देखें।
memmons

@ MichaelG.Emmons: आपका उत्तर बेहतर तरीके से काम करेगा जहां एक संग्रह दृश्य केवल एक बार में एक पूर्ण-आकार वाले सेल को प्रदर्शित करता है। उस स्थिति में, यह समझ में आता है कि UIKit रोटेशन पर शिकायत करता है क्योंकि यह sizeForItemAtIndexPathकॉल करने से पहले क्वेरी करेगा didRotateFromInterfaceOrientation। हालांकि, स्क्रीन पर कई कोशिकाओं के साथ एक संग्रह दृश्य के लिए, रोटेशन से पहले लेआउट को अमान्य करने से दृश्य घूमने से पहले आकार में एक गंदा, दृश्यमान कूद होता है। उस उदाहरण में, मेरा मानना ​​है कि मेरा उत्तर अभी भी सबसे सही कार्यान्वयन है।
फॉलोबेन

@followben सहमत हैं कि प्रत्येक के पास विभिन्न उपयोग मामलों में उनके मुद्दे हैं। इस मामले में, हालांकि, ओपी इंगित I would like to adjust the size of each cell to **completely fit the size of the CollectionView**करता है कि मेरे जवाब में प्रस्तावित समाधान है। यदि आप अपने जवाब में मेरे समाधान को शामिल कर सकते हैं और नोट कर सकते हैं कि कौन सा दृष्टिकोण उन परिस्थितियों में सबसे अच्छा काम करता है जो मेरे लिए पर्याप्त होंगे।
मेमर्स ने

जवाबों:


200

1) आप कई लेआउट ऑब्जेक्ट को बनाए रख सकते हैं और स्वैप कर सकते हैं, लेकिन एक सरल तरीका है। बस अपने UICollectionViewControllerउपवर्ग में निम्नलिखित जोड़ें और आवश्यकतानुसार आकारों को समायोजित करें:

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{    
    // Adjust cell size for orientation
    if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
        return CGSizeMake(170.f, 170.f);
    }
    return CGSizeMake(192.f, 192.f);
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [self.collectionView performBatchUpdates:nil completion:nil];
}

कॉलिंग -performBatchUpdates:completion:लेआउट को अमान्य कर देगा और एनीमेशन के साथ कोशिकाओं का आकार बदल देगा (यदि आप प्रदर्शन करने के लिए कोई अतिरिक्त समायोजन नहीं करते हैं तो आप दोनों ब्लॉक पार्म्स को शून्य पास कर सकते हैं)।

2) आइटम आकारों में हार्डकॉन्डिंग करने के बजाय -collectionView:layout:sizeForItemAtIndexPath, संग्रह की ऊंचाई या चौड़ाई को उन कक्षों की संख्या से विभाजित करें जिन्हें आप स्क्रीन पर फिट करना चाहते हैं। यदि आपके संग्रह दृश्य क्षैतिज या चौड़ाई को स्क्रॉल करता है यदि वह लंबवत स्क्रॉल करता है, तो ऊंचाई का उपयोग करें।


3
सिर्फ कॉल क्यों नहीं [self.collectionView.collectionViewLayout invalidateLayout];?
user102008

7
@ user102008 कॉलिंग invalidateLayoutसही आकार के साथ कोशिकाओं को फिर से आकर्षित -performBatchUpdates:completion:करेगा , लेकिन परिवर्तनों को चेतन करेगा, जो एक बहुत अच्छे एनएचओ दिखता है।
फॉलोबेन

4
मेरे मामले में जब तक मैं स्क्रीन को स्क्रॉल नहीं करता तब तक कोड संग्रह का आकार नहीं बदलता।
newguy

9
didRotateFromInterfaceOrientationIOS 8 में
Jreos

8
IOS8 पर, मैं कॉल कर रहा हूं और इसके ब्लॉक coordinator.animateAlongsideTransitionमें कॉल कर रहा हूं । यह एक अच्छा एनीमेशन प्रभाव देता है। viewWillTransitionToSizeperformBatchUpdatesanimation
माइक टैवर्न

33

यदि आप अतिरिक्त एनिमेशन नहीं लाना चाहते हैं performBatchUpdates:completion:, invalidateLayoutतो संग्रहण को पुनः लोड करने के लिए मजबूर करने के लिए उपयोग करें।

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [self.collectionView.collectionViewLayout invalidateLayout];
}

13

मैंने दो UICollectionViewFlowLayout का उपयोग करके हल किया। एक चित्र के लिए और एक परिदृश्य के लिए। मैं उन्हें अपने संग्रह के दृश्य असाइन करता हूं

self.portraitLayout = [[UICollectionViewFlowLayout alloc] init];
self.landscapeLayout = [[UICollectionViewFlowLayout alloc] init];

UIInterfaceOrientation orientationOnLunch = [[UIApplication sharedApplication] statusBarOrientation];

if (UIInterfaceOrientationIsPortrait(orientationOnLunch)) {
    [self.menuCollectionView setCollectionViewLayout:self.portraitLayout];
} else {
    [self.menuCollectionView setCollectionViewLayout:self.landscapeLayout];
}

फिर मैंने बस इस तरह से अपने संग्रह व्यूफ्लो लॉयआउटडेलगेट के तरीकों को संशोधित किया

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    CGSize returnSize = CGSizeZero;

    if (collectionViewLayout == self.portraitLayout) {
        returnSize = CGSizeMake(230.0, 120.0);
    } else {
        returnSize = CGSizeMake(315.0, 120.0);
    }

    return returnSize;
}

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

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    if (UIInterfaceOrientationIsPortrait(fromInterfaceOrientation)) {
        [self.menuCollectionView setCollectionViewLayout:self.landscapeLayout animated:YES];
    } else {
        [self.menuCollectionView setCollectionViewLayout:self.portraitLayout animated:YES];
    }
}

8

संग्रह दृश्य सेल आकार सेट करने का एक सरल तरीका है:

UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
layout.itemSize = CGSizeMake(cellSize, cellSize);

यकीन नहीं है अगर यह एनिमेटेबल है, हालांकि।


मैं यह देखने के अंदर का उपयोग करने के लिए किया था HaiLao काओ के जवाब के साथ WillLayoutSubviews: stackoverflow.com/a/14776915/2298002
ग्रीनहाउस

7

स्विफ्ट: कलेक्शन व्यू सेल जो स्क्रीन की ऊंचाई का n% है

मुझे एक ऐसी सेल की जरूरत थी जो विचारों की ऊंचाई का एक निश्चित प्रतिशत थी, और डिवाइस रोटेशन के साथ आकार बदल जाएगी।

ऊपर से मदद के साथ, यहां समाधान है

override func viewDidLoad() {
    super.viewDidLoad()
    automaticallyAdjustsScrollViewInsets = false
    // if inside nav controller set to true
}

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    collectionViewLayout.invalidateLayout()
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: 100, height: collectionView.frame.height * 0.9)
}

2

यदि आप उपयोग autolayoutकर रहे हैं । आपको अपने फ्लो लेआउट उपवर्ग में invalidate layoutघूर्णन और समायोजन करते समय बस अपने व्यू कंट्रोलर की आवश्यकता होती है offset

तो, आपके विचार में नियंत्रक -

override func willRotateToInterfaceOrientation(toInterfaceOrientation:     UIInterfaceOrientation, duration: NSTimeInterval) {
    self.galleryCollectionView.collectionViewLayout.invalidateLayout()
}

और अपने में FlowLayout Subclass

override func prepareLayout() {
    if self.collectionView!.indexPathsForVisibleItems().count > 0{
    var currentIndex : CGFloat!
    currentIndex = CGFloat((self.collectionView!.indexPathsForVisibleItems()[0] as! NSIndexPath).row)
    if let currentVal = currentIndex{
        self.collectionView!.contentOffset = CGPointMake(currentIndex * self.collectionView!.frame.width, self.collectionView!.contentOffset.y);
    }   
    }     
}

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