2012-11-25 10 views
98

मैं UICollectionViewFlowLayout के साथ UICollectionView का उपयोग कर रहा हूं।विभिन्न डिवाइस ओरिएंटेशन पर UICollectionViewCell आकार बदलें

मैं

collectionView:layout:sizeForItemAtIndexPath: 

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

सवाल:

1) कैसे एक रोटेशन घटना के बाद एक सेल का आकार बदलने के लिए?

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

+0

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

+0

@ माइकलजी.इमन्स: आपका उत्तर बेहतर काम करेगा जहां संग्रह दृश्य केवल एक ही पूर्ण आकार के सेल को प्रदर्शित करता है। उस स्थिति में, यह समझता है कि UIKit रोटेशन पर शिकायत करता है क्योंकि यह 'didRotateFromInterfaceOrientation' को कॉल करने से पहले 'sizeForItemAtIndexPath' से पूछताछ करेगा। हालांकि, स्क्रीन पर एकाधिक सेल्स के साथ एक संग्रह दृश्य के लिए, घूर्णन से पहले लेआउट को अमान्य करने से देखने से पहले आकार में एक बुरा, दृश्यमान कूद होता है। उस उदाहरण में, मेरा मानना ​​है कि मेरा जवाब अभी भी सबसे सही कार्यान्वयन है। – followben

+0

@followben सहमत हैं कि प्रत्येक के पास विभिन्न उपयोग मामलों में उनके मुद्दे हैं। इस मामले में, ओपी इंगित करता है कि 'मैं प्रत्येक सेल के आकार को समायोजित करना चाहता हूं ** ** संग्रहव्यू ** के आकार को पूरी तरह से फिट करें **' जो वास्तव में मेरे उत्तर में प्रस्तावित समाधान है। यदि आप अपने समाधान में अपना समाधान शामिल कर सकते हैं और ध्यान दें कि कौन सा दृष्टिकोण सबसे अच्छा काम करता है, जिसके अंतर्गत स्थितियां मेरे लिए पर्याप्त होंगी। – memmons

उत्तर

198

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 में आइटम आकारों को हार्डकोड करने के बजाय, संग्रह की ऊंचाई या चौड़ाई को विभाजित करने के बजाय स्क्रीन पर फिट होने वाली कोशिकाओं की संख्या से दृश्य की सीमाएं विभाजित करें। यदि आपका संग्रह दृश्य क्षैतिज या चौड़ाई स्क्रॉल करता है तो ऊंचाई का उपयोग करें यदि यह लंबवत स्क्रॉल करता है।

+0

पांचगल द्वारा प्रस्तावित समाधान भी काम कर रहा है, लेकिन यह वह समाधान है जिसे मैंने पसंद किया था। – Fmessina

+0

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

+0

एनएम, मैंने अभी आमंत्रित किया [self.collectionView प्रदर्शन बैचअपडेट्स: शून्य पूर्णता: शून्य]; viewDidAppear –

13

मैंने दो UICollectionViewFlowLayout का उपयोग करके हल किया। एक चित्र के लिए और एक परिदृश्य के लिए। मैं -viewDidLoad में dinamically मेरी collectionView करने के लिए उन्हें आवंटित

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]; 
} 

तो मैं बस संशोधित मेरी collectionViewFlowLayoutDelgate तरीके इस

- (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]; 
    } 
} 
+0

धन्यवाद !! मैं बाद में आपके समाधान का प्रयास करूंगा और मैं आपको बता दूंगा। – Fmessina

34

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

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

वहाँ संग्रह दृश्य सेल आकार निर्धारित करने के लिए एक आसान तरीका है: अगर यह हालांकि animatable है

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

सुनिश्चित नहीं हैं।

+0

मुझे इसे देखने के अंदर उपयोग करना था, विल फेंग काओ के उत्तर के साथ विल्ललाउटस्यूब्यूव्यू: http://stackoverflow.com/a/14776915/2298002 – greenhouse

2

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

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

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

यह बहुत अच्छा काम करता है! आईओएस 8 में 'willRotateToInterfaceOrientation' को बहिष्कृत किया गया है, लेकिन' viewWillTransitionToSize' इसके लिए भी काम करता है। – keegan3d

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) 
}