UICollectionView में सेल रिक्ति


198

मैं एक सेक्शन में सेल स्पेसिंग कैसे सेट करूँ UICollectionView? मुझे पता है कि एक संपत्ति है जिसे minimumInteritemSpacingमैंने इसे 5.0 पर सेट किया है फिर भी रिक्ति 5.0 दिखाई नहीं दे रही है। मैंने फ्लोआउट प्रतिनिधि पद्धति को लागू किया है।

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{

    return 5.0;
}

फिर भी मुझे वांछित परिणाम नहीं मिल रहा है। मुझे लगता है कि इसकी न्यूनतम रिक्ति है। क्या कोई ऐसा तरीका नहीं है जिसके द्वारा मैं अधिकतम रिक्ति निर्धारित कर सकता हूं?

सिम्युलेटर sc


क्या आपने जाँच की कि यह प्रतिनिधि विधि में प्रवेश कर रहा है या नहीं ..? ब्रेकपॉइंट लगाकर ..
प्रशांत निकम

हाँ, यह प्रतिनिधि में प्रवेश कर रहा है, आईबी में भी मैंने 5 के लिए न्यूनतम सेल रिक्ति निर्धारित की है। लेकिन मुझे नहीं लगता कि न्यूनतम स्थान वह संपत्ति है जो मेरी मदद करेगी क्योंकि यह सुनिश्चित करेगा कि कोशिकाओं के बीच न्यूनतम स्थान 5 होना चाहिए, लेकिन यदि संग्रह दृश्य में अतिरिक्त स्थान है, तो वह उस अतिरिक्त स्थान का उपयोग करेगा। अधिकतम सेल रिक्ति की तरह कुछ होना चाहिए
विशाल सिंह

मेरी भी यही समस्या है। 5px काम नहीं करने लगता है। इसके विपरीत मैं एक UITableView के साथ ऐसा कर सकता हूं, लेकिन UICollectionView के साथ नहीं ...
jerik

मैंने इसे कुछ गणनाओं को करने के लिए तय किया है..मैं इसे टोमोरो पोस्ट करूंगा। :)
विशाल सिंह

2016 के लिए नोट यह आसान है: stackoverflow.com/a/28327193/294884
फटी

जवाबों:


145

मुझे पता है कि विषय पुराना है, लेकिन मामले में किसी को अभी भी यहां सही उत्तर की आवश्यकता है जो आपको चाहिए:

  1. मानक प्रवाह लेआउट को ओवरराइड करें।
  2. उस तरह कार्यान्वयन जोड़ें:

    - (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
        NSArray *answer = [super layoutAttributesForElementsInRect:rect];
    
        for(int i = 1; i < [answer count]; ++i) {
            UICollectionViewLayoutAttributes *currentLayoutAttributes = answer[i];
            UICollectionViewLayoutAttributes *prevLayoutAttributes = answer[i - 1];
            NSInteger maximumSpacing = 4;
            NSInteger origin = CGRectGetMaxX(prevLayoutAttributes.frame);
    
            if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width) {
                CGRect frame = currentLayoutAttributes.frame;
                frame.origin.x = origin + maximumSpacing;
                currentLayoutAttributes.frame = frame;
            }
        }
        return answer;
    }
    

जहाँ मैक्सिमम स्पेस को आप अपनी पसंद के हिसाब से सेट कर सकते हैं। यह ट्रिक इस बात की गारंटी देता है कि कोशिकाओं के बीच की जगह अधिकतम अधिकतम के बराबर होगी !!


तो, हम इसे कहां रखें?
जॉनी

1
हे जॉनी, मानक फ्लो लेआउट से विरासत में मिला है और इस विधि को अपनी कक्षा में कॉपी और पेस्ट करें।
इगा 849

1
ध्यान दें कि आपको बनाने की आवश्यकता नहीं है mutableCopy: आप सरणी की सामग्री को परिवर्तित नहीं कर रहे हैं, लेकिन इसके भीतर वस्तुओं को उत्परिवर्तित कर रहे हैं।
ब्रॉक बोलैंड

5
हो सकता है कि मैं कुछ गलत करूं या यह विचार 100% के लिए काम नहीं कर रहा है, क्योंकि जब मैं अंत तक स्क्रॉल करता हूं तो मैं देखता हूं कि कुछ कोशिकाएं एक-दूसरे को ओवरले करती हैं :(
pash3r

2
महान पद। मैंने कुछ परिस्थितियों में लेआउट की अंतिम पंक्ति के स्वरूपण को परेशान करने के साथ एक त्रुटि का सामना किया। हल करने के लिए मैंने ifउसे और एक अतिरिक्त स्थिति में बदल दिया : if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width && currentLayoutAttributes.frame.origin.x > prevLayoutAttributes.frame.origin.x) {
chrisoneiota

190

प्रारंभिक प्रश्न का समर्थन। मैं 5px पर रिक्ति प्राप्त करने की कोशिश की, UICollectionViewलेकिन यह काम नहीं करता है, साथ ही साथ एक UIEdgeInsetsMake(0,0,0,0)...

UITableView पर मैं x को सीधे निर्दिष्ट करके ऐसा कर सकता हूं, एक पंक्ति में y निर्देशांक ...

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

मेरे UICollectionView कोड का उपयोग करें:

#pragma mark collection view cell layout / size
- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return [self getCellSize:indexPath];  // will be w120xh100 or w190x100
    // if the width is higher, only one image will be shown in a line
}

#pragma mark collection view cell paddings
- (UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(0, 0, 0, 0); // top, left, bottom, right
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {

    return 5.0;
}

अद्यतन: मेरी समस्या का हल, निम्नलिखित कोड के साथ।

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

ViewController.m

#import "ViewController.h"
#import "MagazineCell.h" // created just the default class. 

static NSString * const cellID = @"cellID";

@interface ViewController ()

@end

@implementation ViewController

#pragma mark - Collection view
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 30;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];

    mCell.backgroundColor = [UIColor lightGrayColor];

    return mCell;
}

#pragma mark Collection view layout things
// Layout: Set cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"SETTING SIZE FOR ITEM AT INDEX %d", indexPath.row);
    CGSize mElementSize = CGSizeMake(104, 104);
    return mElementSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

// Layout: Set Edges
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
   // return UIEdgeInsetsMake(0,8,0,8);  // top, left, bottom, right
    return UIEdgeInsetsMake(0,0,0,0);  // top, left, bottom, right
}

@end

यह एक बेहतर जवाब है। कॉलबैक पर एक नज़र डालें जिसे आप UICollectionViewDelegateFlowLayout में समायोजित कर सकते हैं और आप देख सकते हैं कि इसे कैसे ट्विक किया जा सकता है।
cynistersix

1
मुझे लगता है कि यह तभी काम कर सकता है जब आइटम + रिक्ति की चौड़ाई uicollectionview की चौड़ाई के बराबर हो।
xi.lin

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

आप 5px की कोशिकाओं के बीच की चौड़ाई को कहाँ निर्दिष्ट कर रहे हैं?
UKDataGeek

1
स्वीकार किए गए एक की तुलना में बहुत बेहतर उत्तर, मुख्य रूप से क्योंकि UICollectionViewLayout को उप-वर्ग करना केवल एक विधि को ओवरराइड करने की तरह लगता है, और कोई भी तुच्छ मामला नहीं है जिसे अन्य सभी तरीकों को ओवरराइड करने की आवश्यकता है।
सिंधेसिया

80

एक क्षैतिज प्रवाह लेआउट का उपयोग करना, मुझे कोशिकाओं के बीच 10 अंक का अंतर भी मिल रहा था। रिक्ति को हटाने के लिए मुझे शून्य के minimumLineSpacingसाथ-साथ सेट करने की आवश्यकता थी minimumInterItemSpacing

UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init];
flow.itemSize = CGSizeMake(cellWidth, cellHeight);
flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flow.minimumInteritemSpacing = 0;
flow.minimumLineSpacing = 0;

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


34
हैरानी की बात यह है कि, न्यूनतम लाईसेंसिंग कोशिकाओं के बीच क्षैतिज स्थान को प्रभावित करता है।
मैट एच।

4
मुझे भी, मुझे कोशिकाओं के बीच एक क्षैतिज स्क्रॉल और शून्य रिक्ति की आवश्यकता है, और मिनिमलीनस्पेसिंग = 0 कुंजी है।
विंग्जेरो

3
मैं उपयोग किए बिना इस प्रभाव को प्राप्त करने में सक्षम था minimumInteritemSpacing। बस minimumLineSpacing = 0मेरे क्षैतिज लेआउट पर सेटिंग करने से मदों के बीच क्षैतिज अंतर को हटा दिया गया।
Ziewvater

1
यदि आप इसके बारे में सोचते हैं, तो आइटमों के बीच क्षैतिज दूरी एक क्षैतिज रूप से बहने वाले लेआउट के लिए लाइन रिक्ति है। लाइन स्पेसिंग एक विशिष्ट, लंबवत रूप से बहने वाले लेआउट में आइटमों के बीच की ऊर्ध्वाधर दूरी है।
21

62

याद रखें, यह न्यूनतम लाइन स्पेस है , न्यूनतम अंतर आइटम स्पेस या सेल स्पेस नहीं है। क्योंकि आपके कलेक्शन व्यू की स्क्रॉल दिशा HORIZONTAL है

यदि यह लंबवत है, तो आपको कोशिकाओं के बीच क्षैतिज स्थान के लिए क्षैतिज स्थान के लिए सेल स्पेस या इंटर आइटम स्पेस सेट करने की आवश्यकता है।

उद्देश्य-सी संस्करण

- (CGFloat)collectionView:(UICollectionView *)collectionView
                       layout:(UICollectionViewLayout*)collectionViewLayout
    minimumLineSpacingForSectionAtIndex:(NSInteger)section
    {
        return 20;
    }

स्विफ्ट संस्करण:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 20
}

जब मैं 0 वापस करता हूं तो निचला स्थान समाप्त हो जाता है; राइट साइड स्पेस कैसे निकालें?
बेंगलुरू

अरे, मैं आपके सवाल को अच्छी तरह से नहीं समझ पाया। लेकिन मुझे लगता है कि insetForSectionAtIndex वही है जो आप ढूंढ रहे हैं। - (UIEdgeInsets) collectionView: (UICollectionView *) संग्रह दृश्य लेआउट: (UICollectionViewLayout *) संग्रह दृश्यलेयूट insetForSectionAtIndex: (NSInteger) अनुभाग {वापसी UIEdgeInsetsMake (5, 10, 5), 10; }
विन्सेन्ट जॉय

यह क्षैतिज और ऊर्ध्वाधर दोनों के लिए न्यूनतम पंक्ति रिक्ति है।
स्वाति

आपने मेरा दिन (Y) बचा लिया।
उमैर_यूएएस

ओह मेरे शब्द! मैं इस पर विश्वास नहीं कर सकता। धन्यवाद
मागू

36

यह सुनिश्चित करने के लिए इस कोड का प्रयास करें कि आपके पास प्रत्येक आइटम के बीच 5px का अंतर है:

- (UIEdgeInsets)collectionView:(UICollectionView *) collectionView 
                        layout:(UICollectionViewLayout *) collectionViewLayout 
        insetForSectionAtIndex:(NSInteger) section {

    return UIEdgeInsetsMake(0, 0, 0, 5); // top, left, bottom, right
}

- (CGFloat)collectionView:(UICollectionView *) collectionView
                   layout:(UICollectionViewLayout *) collectionViewLayout
  minimumInteritemSpacingForSectionAtIndex:(NSInteger) section {    
    return 5.0;
}

कृपया कोड के रूप में अपने कोड को प्रारूपित करें ताकि यह SO पर अच्छी तरह से प्रदर्शित हो।
कंडक्ट

33

सबसे लोकप्रिय उत्तर का स्विफ्ट संस्करण। कोशिकाओं के बीच का स्थान बराबर होगा cellSpacing

class CustomViewFlowLayout : UICollectionViewFlowLayout {

    let cellSpacing:CGFloat = 4

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        if let attributes = super.layoutAttributesForElementsInRect(rect) {
        for (index, attribute) in attributes.enumerate() {
                if index == 0 { continue }
                let prevLayoutAttributes = attributes[index - 1]
                let origin = CGRectGetMaxX(prevLayoutAttributes.frame)
                if(origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize().width) {
                    attribute.frame.origin.x = origin + cellSpacing
                }
            }
            return attributes
        }
        return nil
    }
}

super.layoutAttributesForElements (in: rect) किसी भी विचार को वापस कर रहा है?
अशोक आर

इसका उपयोग करने वाले अन्य सभी तरीकों की तरह, यह कई पंक्तियों के लिए ठीक से काम नहीं करता है। आंतरायिक, गोलाई-त्रुटि शैली के अंतराल पंक्तियों के बीच बने रहेंगे, यहां तक ​​कि उपयुक्त प्रतिनिधि विधियों और गुणों का उपयोग करने के लिए 0. यह एक UICollectionView रेंडरिंग मुद्दा हो सकता है।
Womble

30

मैंने आईबी का उपयोग करके कोशिकाओं या पंक्तियों के बीच अंतर को कॉन्फ़िगर करने का बहुत आसान तरीका पाया है।

बस स्टोरीबोर्ड / Xib फ़ाइल से UICollectionView का चयन करें और नीचे की छवि में निर्दिष्ट आकार निरीक्षक में क्लिक करें ।

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

प्रोग्राम को कॉन्फ़िगर करने के लिए निम्नलिखित गुणों का उपयोग करें।

1) पंक्तियों के बीच जगह स्थापित करने के लिए।

[self.collectionView setMinimumLineSpacing:5];

2) वस्तुओं / कोशिकाओं के बीच स्थान स्थापित करने के लिए।

[self.collectionView setMinimumInteritemSpacing:5];

1
न्यूनतम स्थान, जो निर्दिष्ट मूल्य से अधिक होगा और हमेशा निर्दिष्ट मूल्य से अधिक नहीं होगा।
विशाल सिंह

21

कृपया ध्यान दें कि संपत्ति का नाम न्यूनतमInterItemSpacing है । यह उन वस्तुओं के बीच न्यूनतम अंतर होगा जो सटीक रिक्ति नहीं हैं। यदि आप कुछ मूल्य पर न्यूनतमInterItemSpacing सेट करते हैं, तो आप आश्वस्त कर सकते हैं कि रिक्ति न होना उससे कम मूल्य है। लेकिन वहाँ एक मौका है एक उच्च मूल्य मिलता है।

असल में आइटम के बीच अंतर पर कई कारकों पर निर्भर करता है itemSize और sectionInset । संग्रह देखें गतिशील रूप से इन मूल्यों के आधार पर सामग्री रखें। तो आप सटीक रिक्ति का आश्वासन नहीं दे सकते। आप के साथ कुछ परीक्षण और त्रुटि करना चाहिए sectionInset और minimumInterItemSpacing


1
@ एनील एज कीड़े? : डी
नाइटफ्यू

10
आपके अनुभागों में कीड़े हो सकते हैं।
नेस्टर

24
कीट == बग && कीट! = इनसेट :)
नेस्टर

16

स्विफ्ट 3.0, एक्सकोड 8 का उत्तर

1. सुनिश्चित करें कि आप संग्रह दृश्य प्रतिनिधि सेट करें

class DashboardViewController: UIViewController {
    @IBOutlet weak var dashboardCollectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        dashboardCollectionView.delegate = self
    }
}

2.Implement UICollectionViewDelegateFlowLayout प्रोटोकॉल, नहीं UICollectionViewDelegate।

extension DashboardViewController: UICollectionViewDelegateFlowLayout {
    fileprivate var sectionInsets: UIEdgeInsets {
        return .zero
    }

    fileprivate var itemsPerRow: CGFloat {
        return 2
    }

    fileprivate var interitemSpace: CGFloat {
        return 5.0
    }

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        let sectionPadding = sectionInsets.left * (itemsPerRow + 1)
        let interitemPadding = max(0.0, itemsPerRow - 1) * interitemSpace
        let availableWidth = collectionView.bounds.width - sectionPadding - interitemPadding
        let widthPerItem = availableWidth / itemsPerRow

        return CGSize(width: widthPerItem, height: widthPerItem)
    }

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        insetForSectionAt section: Int) -> UIEdgeInsets {
        return sectionInsets
    }

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0.0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return interitemSpace
    }
}

1
सोचिए आप वहां की जनता को हटा सकते हैं। ठीक काम करना चाहिए, और अन्य सभी दुर्गंधों के साथ संगत होना चाहिए।
एडवर्ड पॉटर

क्या यह कार्य ऊर्ध्वाधर स्क्रॉल संग्रह दृश्य के लिए होगा? मेरे पास संग्रह दृश्य है जहां इसे iPhone 6s और 6s Plus जैसे उपकरणों पर क्षैतिज रूप से 2 सेल दिखाना चाहिए, लेकिन इससे कम यानी 5s, 5 और SE के लिए केवल एक सेल दिखाना चाहिए। मेरा वर्तमान कोड काम कर रहा है, लेकिन 6s प्लस डिवाइस में कोशिकाओं के बीच का अंतर बहुत अधिक है और बदसूरत लग रहा है और मैं उस अंतर को कम करने की कोशिश कर रहा हूं और यह एकमात्र आवश्यकता है क्योंकि अन्य सभी डिवाइस मेरे डिजाइन के अनुसार काम कर रहे हैं।
अनीसब

11

रिक्ति के लिए सरल कोड

let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.minimumInteritemSpacing = 10 // Some float value

3
क्षैतिज सेल रिक्ति के लिए उपयोग करना चाहिए: न्यूनतम लिंक
अल्फी

9

जवाब मतदान (और भी तेज संस्करण ) एक छोटा सा मुद्दा है: सही पर एक बड़ा अंतर नहीं होगा।

ऐसा इसलिए है क्योंकि फ्लो लेफ्ट व्यवहार के साथ फ्लो लेआउट सेल स्पेसिंग को सटीक बनाता है।

मेरा समाधान अनुभाग इनसेट में हेरफेर करना है, ताकि अनुभाग संरेखित केंद्र हो, फिर भी रिक्ति बिल्कुल निर्दिष्ट है।

नीचे स्क्रीनशॉट में, आइटम / लाइन रिक्ति बिल्कुल 8pt है, जबकि लेफ्ट और राइट इनसेट 8pt से बड़ा होगा (इसे केंद्र संरेखित करने के लिए):

समान रूप से स्थानिक कोशिकाएँ

स्विफ्ट कोड जैसे:

private let minItemSpacing: CGFloat = 8
private let itemWidth: CGFloat      = 100
private let headerHeight: CGFloat   = 32

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Create our custom flow layout that evenly space out the items, and have them in the center
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: itemWidth, height: itemWidth)
    layout.minimumInteritemSpacing = minItemSpacing
    layout.minimumLineSpacing = minItemSpacing
    layout.headerReferenceSize = CGSize(width: 0, height: headerHeight)

    // Find n, where n is the number of item that can fit into the collection view
    var n: CGFloat = 1
    let containerWidth = collectionView.bounds.width
    while true {
        let nextN = n + 1
        let totalWidth = (nextN*itemWidth) + (nextN-1)*minItemSpacing
        if totalWidth > containerWidth {
            break
        } else {
            n = nextN
        }
    }

    // Calculate the section inset for left and right. 
    // Setting this section inset will manipulate the items such that they will all be aligned horizontally center.
    let inset = max(minItemSpacing, floor( (containerWidth - (n*itemWidth) - (n-1)*minItemSpacing) / 2 ) )
    layout.sectionInset = UIEdgeInsets(top: minItemSpacing, left: inset, bottom: minItemSpacing, right: inset)

    collectionView.collectionViewLayout = layout
}

1
मुझे एक 'NSInvalidArgumentException' मिलती है, कारण: '*** setObjectForKey: ऑब्जेक्ट शून्य नहीं हो सकता (कुंजी: <NSIndexPath: 0xc000000000000016> {लंबाई: 2, पथ = 0 - 0})' अनकहा अपवाद।
डफ्टवॉली

... अगर मैं गलत नहीं हूं, तो आपका लूप बराबर है: let n = Int((containerWidth + minItemSpacing)/((itemWidth+minItemSpacing)))
DaftWooly

के रूप में कोड का उपयोग नहीं किया है, लेकिन इसने मुझे संग्रह दृश्य के लिए मेरे आउट फ्लो लेआउट को लागू करने के लिए सबसे अच्छा संदर्भ दिया। चीयर्स
Dima Gimburg

8

UICollectionViewDelegateFlowLayoutअपनी हेडर फ़ाइल में प्रोटोकॉल को परिभाषित करें ।

UICollectionViewDelegateFlowLayoutइस तरह से प्रोटोकॉल के निम्नलिखित तरीके को लागू करें:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    return UIEdgeInsetsMake(5, 5, 5, 5);
}

Apple प्रलेखन UIEdgeInsetMakeविधि देखने के लिए यहां क्लिक करें


4

स्टोरीबोर्ड दृष्टिकोण

अपने स्टोरीबोर्ड में CollectionView का चयन करें और आकार निरीक्षक पर जाएं और 5 के रूप में कोशिकाओं और लाइनों के लिए न्यूनतम रिक्ति सेट करें

प्रोग्राम 5 को स्विफ्ट करें

lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal

        //Provide Width and Height According to your need
        let width = UIScreen.main.bounds.width / 4
        let height = UIScreen.main.bounds.height / 10
        layout.itemSize = CGSize(width: width, height: height)

        //For Adjusting the cells spacing
        layout.minimumInteritemSpacing = 5
        layout.minimumLineSpacing = 5

        return UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
    }()

3

यदि आप वास्तविक सेल आकार को छुए बिना रिक्ति को मोड़ना चाहते हैं, तो यह वह समाधान है जो मेरे लिए सबसे अच्छा काम करता है। #xcode 9 # tvOS11 # iOS11 #swift

इसलिए UICollectionViewDelegateFlowLayout में , अगली विधियों को लागू करने के लिए बदलाव करें, चाल यू दोनों का उपयोग करना है, और प्रलेखन वास्तव में मुझे उस दिशा में सोचने के लिए इशारा नहीं कर रहा था। : डी

open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return cellSpacing
}

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return cellSpacing
}

2

मैं मोनोटॉक का उपयोग कर रहा हूं, इसलिए नाम और कोड थोड़ा अलग होगा, लेकिन आप यह सुनिश्चित करके कर सकते हैं कि संग्रह की चौड़ाई बराबर (x * सेल चौड़ाई) + (x-1) * x = राशि के साथ न्यूनतम हो प्रति पंक्ति की कोशिकाएं।

बस अपने मिनिममइंटरमिटेमस्पेसिंग और सेल की चौड़ाई के आधार पर निम्न चरणों का पालन करें

1) हम सेल आकार + वर्तमान इनसेट्स + न्यूनतम रिक्ति के आधार पर प्रति पंक्ति वस्तुओं की मात्रा की गणना करते हैं

float currentTotalWidth = CollectionView.Frame.Width - Layout.SectionInset.Left - Layout.SectionInset.Right (Layout = flowlayout)
int amountOfCellsPerRow = (currentTotalWidth + MinimumSpacing) / (cell width + MinimumSpacing)

2) अब आपके पास संग्रह दृश्य के लिए अपेक्षित चौड़ाई की गणना करने के लिए सभी जानकारी है

float totalWidth =(amountOfCellsPerRow * cell width) + (amountOfCellsPerRow-1) * MinimumSpacing

3) इसलिए वर्तमान चौड़ाई और अपेक्षित चौड़ाई के बीच का अंतर है

float difference = currentTotalWidth - totalWidth;

4) अब इनसेट्स को समायोजित करें (इस उदाहरण में हम इसे दाईं ओर जोड़ते हैं, इसलिए संग्रह की बाईं स्थिति समान रहती है

Layout.SectionInset.Right = Layout.SectionInset.Right + difference;

2

मेरे पास एक क्षैतिज UICollectionViewऔर उपवर्ग है UICollectionViewFlowLayout। संग्रह दृश्य में बड़ी कोशिकाएँ होती हैं, और केवल एक समय में उनमें से एक पंक्ति दिखाई देती है, और संग्रह दृश्य स्क्रीन की चौड़ाई पर फिट बैठता है।

मैंने iago849 के उत्तर की कोशिश की और यह काम कर गया, लेकिन फिर मुझे पता चला कि मुझे उसके उत्तर की आवश्यकता भी नहीं थी। किसी कारण के लिए, minimumInterItemSpacingकुछ भी नहीं करता है। मेरी वस्तुओं / कोशिकाओं के बीच अंतर को पूरी तरह से नियंत्रित किया जा सकता है minimumLineSpacing

यकीन नहीं है कि यह इस तरह से काम करता है, लेकिन यह काम करता है।


1
यह सच प्रतीत होता है - अजीब तरह से "लाइनों" मूल्य है, वास्तव में, क्षैतिज लेआउट के मामले में वस्तुओं के बीच विभाजक।
फेटी

अरे @ user3344977 - अच्छा लगता है। मैंने इस मुद्दे को एक अलग प्रश्न के रूप में अलग करने का फैसला किया जो सीधे क्षैतिज स्क्रॉल संग्रह विचारों को संबोधित करता है ताकि कुछ लोगों के लिए ढूंढना आसान हो जाए। मैं आपके उत्तर का संदर्भ देता हूं। मेरा सवाल यहाँ है: stackoverflow.com/q/61774415/826946
एंडी वेनस्टेन

1

मैं ओपी के समान एक समस्या पर ठोकर खाई। दुर्भाग्य से स्वीकृत जवाब मेरे लिए काम नहीं करता था क्योंकि सामग्री की सामग्री collectionViewठीक से केंद्रित नहीं होगी। इसलिए मैं एक अलग समाधान के साथ आया था जिसके लिए केवल यह आवश्यक है कि सभी आइटम collectionViewएक ही चौड़ाई के हों , जो कि प्रश्न में ऐसा प्रतीत हो:

#define cellSize 90

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    float width = collectionView.frame.size.width;
    float spacing = [self collectionView:collectionView layout:collectionViewLayout minimumInteritemSpacingForSectionAtIndex:section];
    int numberOfCells = (width + spacing) / (cellSize + spacing);
    int inset = (width + spacing - numberOfCells * (cellSize + spacing) ) / 2;

    return UIEdgeInsetsMake(0, inset, 0, inset);
}

यह कोड सुनिश्चित करेगा कि मूल्य द्वारा लौटाया गया मूल्य ...minimumInteritemSpacing...हर के बीच सटीक अंतर होगा collectionViewCellऔर इसके बाद गारंटी होगी कि सभी कोशिकाएं एक साथ केन्द्रित होंगीcollectionView


यह बहुत मजेदार है। लेकिन मैं सोच रहा था कि क्या एक समान समाधान तत्वों के बीच ऊर्ध्वाधर रिक्ति पर लागू किया जा सकता है
p0lAris

यदि आपके पास क्षैतिज स्क्रॉलिंग है तो वर्टिकल स्पेसिंग?
luk2302

1

इसके बाद के संस्करण समाधान द्वारा Vojtech-Vrbka सही है, लेकिन यह एक चेतावनी से चलाता है:

चेतावनी: UICollectionViewFlowLayout ने अनुक्रमणिका पथ के लिए फ्रेम बेमेल को कैश किया है - कैश्ड मान: ऐसा होने की संभावना है क्योंकि प्रवाह लेआउट उपवर्ग लेआउट को संशोधित किया गया है विशेषताओं को UICollectionViewFlowLayout द्वारा कॉपी किए बिना लौटाया गया है

निम्नलिखित कोड को इसे ठीक करना चाहिए:

class CustomViewFlowLayout : UICollectionViewFlowLayout {

   let cellSpacing:CGFloat = 4

   override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
       let original = super.layoutAttributesForElementsInRect(rect)

       if let original = original {
           let attributes = NSArray.init(array: original, copyItems: true) as! [UICollectionViewLayoutAttributes]

           for (index, attribute) in attributes.enumerate() {
                if index == 0 { continue }
                let prevLayoutAttributes = attributes[index - 1]
                let origin = CGRectGetMaxX(prevLayoutAttributes.frame)
                if(origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize().width) {
                    attribute.frame.origin.x = origin + cellSpacing
                }
            }
            return attributes
       }
       return nil
   }
}

2
इस दृष्टिकोण का उपयोग करने वाले SO पर अन्य उत्तरों की तरह, यह संग्रह दृश्य की चौड़ाई में फिटिंग कोशिकाओं के लिए काम करता है, लेकिन रुक-रुक कर, चर-ऊंचाई अंतराल अभी भी पंक्तियों के बीच बने रहते हैं। यह उस तरीके की एक सीमा हो सकती है जिस तरह से कलेक्शन वास्तव में प्रस्तुत करता है।
वोमबल

1

स्विफ्ट 3 संस्करण

बस एक UICollectionViewFlowLayout उपवर्ग बनाएँ और इस विधि को पेस्ट करें।

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let answer = super.layoutAttributesForElements(in: rect) else { return nil }

        for i in 1..<answer.count {
            let currentAttributes = answer[i]
            let previousAttributes = answer[i - 1]

            let maximumSpacing: CGFloat = 8
            let origin = previousAttributes.frame.maxX

            if (origin + maximumSpacing + currentAttributes.frame.size.width < self.collectionViewContentSize.width && currentAttributes.frame.origin.x > previousAttributes.frame.origin.x) {
                var frame = currentAttributes.frame
                frame.origin.x = origin + maximumSpacing
                currentAttributes.frame = frame
            }
        }

        return answer
}

यह क्षैतिज फिटिंग के लिए काम करता है, लेकिन गैप पंक्तियों के बीच रहेगा, भले ही मिनिमम स्पेसिंगफोरसैंटरएट 0 पर वापस जाने के लिए सेट हो, और लेआउट। मिनिमम लाइटलाइनिंग 0. पर सेट हो। इसके अलावा, कलेक्शन व्यू में एक टच ऐप को क्रैश कर देगा, पहला लूप आउट होने के कारण सीमा के।
Womble

1

मैंने iago849 के उत्तर की कोशिश की है और इसने काम किया है।

स्विफ्ट 4

open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    guard let answer = super.layoutAttributesForElements(in: rect) else {
        return nil
    }
    let count = answer.count
    for i in 1..<count {
        let currentLayoutAttributes = answer[i]
        let prevLayoutAttributes = answer[i-1]
        let origin = prevLayoutAttributes.frame.maxX
        if (origin + CGFloat(spacing) + currentLayoutAttributes.frame.size.width) < self.collectionViewContentSize.width && currentLayoutAttributes.frame.origin.x > prevLayoutAttributes.frame.origin.x {
            var frame = currentLayoutAttributes.frame
            frame.origin.x = origin + CGFloat(spacing)
            currentLayoutAttributes.frame = frame
        }
    }
    return answer
}

यहाँ github प्रोजेक्ट के लिए लिंक दिया गया है। https://github.com/vishalwaka/MultiTags


0

पिछले संस्करणों ने वास्तव में वर्गों के साथ काम नहीं किया> 1. इसलिए मेरा समाधान यहां पाया गया था https://codentrick.com/create-a-tag-flow-layout-with-uicollectionview/ । आलसी लोगों के लिए:

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
    var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
    // use a value to keep track of left margin
    var leftMargin: CGFloat = 0.0;
    for attributes in attributesForElementsInRect! {
        let refAttributes = attributes 
        // assign value if next row
        if (refAttributes.frame.origin.x == self.sectionInset.left) {
            leftMargin = self.sectionInset.left
        } else {
            // set x position of attributes to current margin
            var newLeftAlignedFrame = refAttributes.frame
            newLeftAlignedFrame.origin.x = leftMargin
            refAttributes.frame = newLeftAlignedFrame
        }
        // calculate new value for current margin
        leftMargin += refAttributes.frame.size.width + 10
        newAttributesForElementsInRect.append(refAttributes)
    }

    return newAttributesForElementsInRect
}

0

मुझे स्वीकृत उत्तर में समस्या है, इसलिए मैंने इसे अपडेट किया, यह मेरे लिए काम कर रहा है:

@interface MaxSpacingCollectionViewFlowLayout : UICollectionViewFlowLayout
@property (nonatomic,assign) CGFloat maxCellSpacing;
@end

।म

@implementation MaxSpacingCollectionViewFlowLayout

- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];

    if (attributes.count <= 0) return attributes;

    CGFloat firstCellOriginX = ((UICollectionViewLayoutAttributes *)attributes[0]).frame.origin.x;

    for(int i = 1; i < attributes.count; i++) {
        UICollectionViewLayoutAttributes *currentLayoutAttributes = attributes[i];
        if (currentLayoutAttributes.frame.origin.x == firstCellOriginX) { // The first cell of a new row
            continue;
        }

        UICollectionViewLayoutAttributes *prevLayoutAttributes = attributes[i - 1];
        CGFloat prevOriginMaxX = CGRectGetMaxX(prevLayoutAttributes.frame);
        if ((currentLayoutAttributes.frame.origin.x - prevOriginMaxX) > self.maxCellSpacing) {
            CGRect frame = currentLayoutAttributes.frame;
            frame.origin.x = prevOriginMaxX + self.maxCellSpacing;
            currentLayoutAttributes.frame = frame;
        }
    }
    return attributes;
}

@end

0

Swift 3इंस्टाग्राम की तरह सेल लाइन रिक्ति में मेरा समाधान :

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

lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.backgroundColor = UIColor.rgb(red: 227, green: 227, blue: 227)
    cv.showsVerticalScrollIndicator = false
    layout.scrollDirection = .vertical
    layout.minimumLineSpacing = 1
    layout.minimumInteritemSpacing = 1
    return cv
}()

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    switch UIDevice.current.modelName {
    case "iPhone 4":
        return CGSize(width: 106, height: 106)
    case "iPhone 5":
        return CGSize(width: 106, height: 106)
    case "iPhone 6,7":
        return CGSize(width: 124, height: 124)
    case "iPhone Plus":
        return CGSize(width: 137, height: 137)
    default:
        return CGSize(width: frame.width / 3, height: frame.width / 3)
    }
}

डिवाइस का पता कैसे लगाएं प्रोग्रामेटिकली: https://stackoverflow.com/a/26962452/6013170


0

ठीक है, यदि आप एक क्षैतिज संग्रह दृश्य बना रहे हैं, तो कोशिकाओं के बीच जगह देने के लिए, आपको संपत्ति सेट करने की आवश्यकता है minimumLineSpacing


-1

इस विधि के साथ खेलने का प्रयास करें:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
                    layout:(UICollectionViewLayout*)collectionViewLayout
    insetForSectionAtIndex:(NSInteger)section {

    UIEdgeInsets insets = UIEdgeInsetsMake(?, ?, ?, ?);

    return insets;
}

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