কীভাবে একটি ইউআইসিকলিকেশনভিউয়ের ঘরগুলি সারিবদ্ধ করবেন?


98

আমি বর্তমানে UICollectionViewব্যবহারকারীর ইন্টারফেস গ্রিডের জন্য ব্যবহার করছি এবং এটি দুর্দান্ত কাজ করে। তবে আমি অনুভূমিক স্ক্রোলিং সক্ষম করতে চাই। গ্রিড প্রতি পৃষ্ঠায় 8 টি আইটেম সমর্থন করে এবং যখন আইটেমের মোট সংখ্যা হয় 4 বলুন, আইটেমগুলি এভাবে অনুভূমিক স্ক্রোলের দিকটি সক্ষম করে সজ্জিত করা উচিত:

0 0 x x
0 0 x x

এখানে 0 -> সংগ্রহ আইটেম এবং এক্স -> খালি ঘর

এগুলি কেন্দ্রের মতো করে সারিবদ্ধ করার কোনও উপায় আছে:

x 0 0 x
x 0 0 x

যাতে বিষয়বস্তু আরও পরিষ্কার দেখাচ্ছে?

এছাড়াও নীচের ব্যবস্থাটি একটি সমাধান হতে পারে যা আমি প্রত্যাশা করছি।

0 0 0 0
x x x x

উত্তর:


80

আমি মনে করি আপনি এর মতো কিছু প্রয়োগ করে একক লাইন চেহারা অর্জন করতে পারেন:

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

কীভাবে একটি একক লাইনে বিষয়বস্তুকে জোর করা যায় তা নির্ধারণ করতে আপনাকে সেই নম্বরটি নিয়ে খেলতে হবে। প্রথম 0, শীর্ষ প্রান্ত আর্গুমেন্ট, আপনি এটিও সামঞ্জস্য করতে পারেন, আপনি যদি স্ক্রিনে উল্লম্বভাবে বিষয়বস্তুটি কেন্দ্র করতে চান।


4
এটি ভাল সমাধান ধন্যবাদ, তবে এটির জন্য আমার পক্ষে কিছু অতিরিক্ত গণনা প্রয়োজন।
আরভিএন

আপনি এই মানগুলি কীভাবে গণনা করবেন?
jjxtra

7
গতিশীলভাবে পোকামাকড় গণনা করতে: সিজিফ্লোট লেফট ইনসেট = (কালেকশনভিউ.ফ্রেম.সাইজ.উইথথ -40 * [কালেকশনভিউ নম্বরঅফআইটেমসইনসেকশন: বিভাগ]) / 2; 40 = কক্ষের আকার
আব্দুলিয়াম রেহমানিয়াস

4
@ আবদুলুলিয়াম রেহমানিয়াস তবে এটি ধরে নেয় যে কোষগুলি অনুভূমিকভাবে ব্যবধানহীন নয়। সাধারণত তারা হয়। এবং প্রকৃত স্থানগুলি নির্ধারণ করা অবিচ্ছিন্ন বলে মনে হয় কারণ এটি minimumInteritemSpacingকেবল তাদের ন্যূনতম নির্দেশ করে।
ড্রুक्स

4
এটা আসলে হওয়া উচিত return UIEdgeInsetsMake(0, 100, 0, 100);। সেখানে থাকে তবে অতিরিক্ত স্থান, সংগ্রহ দৃশ্য অন্তর্বর্তী ব্যবধান প্রসারিত হবে, তাই আপনি নিশ্চিত LeftInset + + CellWidth * Ncells + + CellSpacing * (Ncells -1) + + RightInset = CollectionViewWidth করতে হবে
vish

85

যারা কেন্দ্র-বিন্যস্ত, গতিশীল-প্রস্থের সংগ্রহদর্শন ঘরগুলির সমাধান খুঁজছেন , আমি যেমন ছিলাম, তেমন জন্য কেন্দ্র-সারিবদ্ধ সাবক্লাস তৈরি করতে বাম-প্রান্তিককরণ সংস্করণটির জন্য আমি এঞ্জেলের উত্তরটি সংশোধন করে শেষ করেছি UICollectionViewFlowLayout

সেন্টারএলিন্ডড কালেকশনভিউফ্লোলোআউট

// NOTE: Doesn't work for horizontal layout!
class CenterAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let superAttributes = super.layoutAttributesForElements(in: rect) else { return nil }
        // Copy each item to prevent "UICollectionViewFlowLayout has cached frame mismatch" warning
        guard let attributes = NSArray(array: superAttributes, copyItems: true) as? [UICollectionViewLayoutAttributes] else { return nil }
        
        // Constants
        let leftPadding: CGFloat = 8
        let interItemSpacing = minimumInteritemSpacing
        
        // Tracking values
        var leftMargin: CGFloat = leftPadding // Modified to determine origin.x for each item
        var maxY: CGFloat = -1.0 // Modified to determine origin.y for each item
        var rowSizes: [[CGFloat]] = [] // Tracks the starting and ending x-values for the first and last item in the row
        var currentRow: Int = 0 // Tracks the current row
        attributes.forEach { layoutAttribute in
            
            // Each layoutAttribute represents its own item
            if layoutAttribute.frame.origin.y >= maxY {
                
                // This layoutAttribute represents the left-most item in the row
                leftMargin = leftPadding
                
                // Register its origin.x in rowSizes for use later
                if rowSizes.count == 0 {
                    // Add to first row
                    rowSizes = [[leftMargin, 0]]
                } else {
                    // Append a new row
                    rowSizes.append([leftMargin, 0])
                    currentRow += 1
                }
            }
            
            layoutAttribute.frame.origin.x = leftMargin
            
            leftMargin += layoutAttribute.frame.width + interItemSpacing
            maxY = max(layoutAttribute.frame.maxY, maxY)
            
            // Add right-most x value for last item in the row
            rowSizes[currentRow][1] = leftMargin - interItemSpacing
        }
        
        // At this point, all cells are left aligned
        // Reset tracking values and add extra left padding to center align entire row
        leftMargin = leftPadding
        maxY = -1.0
        currentRow = 0
        attributes.forEach { layoutAttribute in
            
            // Each layoutAttribute is its own item
            if layoutAttribute.frame.origin.y >= maxY {
                
                // This layoutAttribute represents the left-most item in the row
                leftMargin = leftPadding
                
                // Need to bump it up by an appended margin
                let rowWidth = rowSizes[currentRow][1] - rowSizes[currentRow][0] // last.x - first.x
                let appendedMargin = (collectionView!.frame.width - leftPadding  - rowWidth - leftPadding) / 2
                leftMargin += appendedMargin
                
                currentRow += 1
            }
            
            layoutAttribute.frame.origin.x = leftMargin
            
            leftMargin += layoutAttribute.frame.width + interItemSpacing
            maxY = max(layoutAttribute.frame.maxY, maxY)
        }
        
        return attributes
    }
}

সেন্টারএলিন্ডড কালেকশনভিউফ্লোলোআউট


4
এর ফলে, নিম্নলিখিত সতর্কতা দিয়েছেন, যদিও এই সম্ভবত ঘটছে কারণ প্রবাহ বিন্যাস উপশ্রেণী xxxx.CustomCollectionViewFlowLayout তাদের অনুলিপি সংশোধন ছাড়া UICollectionViewFlowLayout দ্বারা ফিরে বৈশিষ্ট্যাবলী পরিবর্তন করা হয়, আমি [থেকে কোড ব্যবহার করা stackoverflow.com/a/36315664/1067951] guard let superArray = super.layoutAttributesForElementsInRect(rect) else { return nil } guard let attributes = NSArray(array: superArray, copyItems: true) as? [UICollectionViewLayoutAttributes] else { return nil }
রাম

পোস্ট করার জন্য আপনাকে ধন্যবাদ। এটি অর্জনের চেষ্টা করে কয়েক দিন ব্যয় করলেন!
ইয়াং

কাজের জন্য এবং সম্প্রদায়ের সাথে ফলাফল ভাগ করে নেওয়ার জন্য আপনাকে ধন্যবাদ। আমি কোড আপডেট করেছি। প্রথমত, আমি @ রম দ্বারা প্রস্তাবিত পরিবর্তনগুলি যুক্ত করেছি। দ্বিতীয়ত, আমি interItemSpacingডিফল্ট ব্যবহার করতে পরিবর্তন করি minimumInteritemSpacing
ক্যালিন

ডি্যাম্বারে এটি ধরার জন্য আমার কাছে ইউআইকোলিকেশনভিউফ্লোলাউটব্রেইকফোর্ডআইনডল সাইজে একটি প্রতীকী ব্রেকআপপয়েন্ট তৈরি করার একটি সমস্যা রয়েছে of ইউআইসিএল্লেশনভিউফ্লোলোআউটের আচরণটি সংজ্ঞায়িত করা হয়নি কারণ: আইটেমের প্রস্থটি ইউআইসিএল্লেশনভিউয়ের প্রস্থের চেয়ে কম হতে হবে বিভাগের ইনসেটগুলি বাম এবং ডান মানগুলি বিয়োগ করবে, বিষয়বস্তু ইনসেটগুলি বাম এবং ডান মানগুলি বিয়োগ করবে
EI ক্যাপ্টেন v2.0

4
ভিউডিডলড () এ জ্যাকটি এর মতো ব্যবহার করুন। সংগ্রহ
ভিউনাম.কম.লোকশনভিউলয়েআউট

57

এখানে শীর্ষস্থানীয় সমাধানগুলি আমার বাইরে-বাক্সটির জন্য কাজ করে না, তাই আমি এটি নিয়ে এসেছি যা প্রবাহ বিন্যাস এবং কেবলমাত্র একটি বিভাগ সহ যে কোনও অনুভূমিক স্ক্রোলিং সংগ্রহ দর্শনের জন্য কাজ করা উচিত:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
    {
    // Add inset to the collection view if there are not enough cells to fill the width.
    CGFloat cellSpacing = ((UICollectionViewFlowLayout *) collectionViewLayout).minimumLineSpacing;
    CGFloat cellWidth = ((UICollectionViewFlowLayout *) collectionViewLayout).itemSize.width;
    NSInteger cellCount = [collectionView numberOfItemsInSection:section];
    CGFloat inset = (collectionView.bounds.size.width - (cellCount * cellWidth) - ((cellCount - 1)*cellSpacing)) * 0.5;
    inset = MAX(inset, 0.0);
    return UIEdgeInsetsMake(0.0, inset, 0.0, 0.0);
    }

আপনার সেলস্যাক্সিংটি 'সেলসઉન્ટ - 1' দিয়ে গুণতে হবে সেল সেল থেকে নয়। এটির ক্ষেত্রে আরও স্পষ্ট হয় যখন কেবলমাত্র একটি কোষ থাকে: কোষগুলির মধ্যে কোনও স্থান থাকে না।
ফ্যাবিও অলিভিরা

এবং 'ইনসেট = ম্যাক্স (ইনসেট, ০.০)' ব্যবহার করার জন্য একটি ন্যূনতম ইনসেটও থাকতে হবে; লাইন এটি দেখতে 'ইনসেট = ম্যাক্স (ইনসেট, ন্যূনতম ইনসেট);' এর মতো লাগবে। আপনার ডানদিকে একই ন্যূনতমতম ইনসেট প্রয়োগ করা উচিত। সংগ্রহের দর্শনগুলি প্রান্তের ডানদিকে প্রসারিত করার সময় আরও ভাল দেখায় :)
ফ্যাবিও অলিভিরা

এই সলিউশন এবং @ সায়ন থেকে প্রাপ্ত উভয়ই কোষের আকারটি ধ্রুবক হলে সমানভাবে কাজ করে। কেউ কি জানতে পারবেন কীভাবে কোষগুলির আকার পাবেন? সেলফর্ম আইটেমটিডেক্সপথ এবং দৃশ্যমান সেলগুলি কেবল যখন সংগ্রহভিউ দৃশ্যমান হয় তখন তথ্য ফিরে আসে বলে মনে হয় - এবং জীবনচক্রের এই সময়ে, এটি হয় না।
ড্যান লঘনে 11

@ সিগফৌল্ট আমি এটি প্রয়োগ করেছি এবং যতক্ষণ না আমি বামদিকে স্ক্রোল করার চেষ্টা করেছি এটি মাঝখানে ফিরে আসে fine
অনিরুদ্ধ মহলে

34

গতিশীলভাবে পোকামাকড় গণনা করা সহজ, এই কোডটি সর্বদা আপনার কোষকে কেন্দ্র করে রাখবে:

NSInteger const SMEPGiPadViewControllerCellWidth = 332;

...

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

    NSInteger numberOfCells = self.view.frame.size.width / SMEPGiPadViewControllerCellWidth;
    NSInteger edgeInsets = (self.view.frame.size.width - (numberOfCells * SMEPGiPadViewControllerCellWidth)) / (numberOfCells + 1);

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

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [self.collectionView.collectionViewLayout invalidateLayout];
}

4
আপনার পরিবর্তন কি ছিল?
সিরিস

4
@ সিরিজ এসএমইপিগিপ্যাডভিউ কনট্রোলারসেলউইথের পরিবর্তে আপনি সংগ্রহ ভিউলাওআউট.সাইটমসাইজ.ইউইথ ব্যবহার করতে পারেন, এবং সম্ভবত এটিই ছিল তাঁর পরিবর্তন
মাইকেল জাবোরোভস্কি

21

অন্যান্য উত্তরের মতো, এটি একটি গতিশীল উত্তর যা স্থির আকারের কক্ষগুলির জন্য কাজ করা উচিত। আমি যে পরিবর্তনটি করেছি তা হ'ল আমি দু'দিকে প্যাডিং রেখেছি। আমি যদি এটি না করে থাকি তবে আমি সমস্যাগুলি ভোগ করেছি।


উদ্দেশ্য গ

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

    NSInteger numberOfItems = [collectionView numberOfItemsInSection:section];
    CGFloat combinedItemWidth = (numberOfItems * collectionViewLayout.itemSize.width) + ((numberOfItems - 1) * collectionViewLayout.minimumInteritemSpacing);
    CGFloat padding = (collectionView.frame.size.width - combinedItemWidth) / 2;

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

সুইফট

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let numberOfItems = CGFloat(collectionView.numberOfItems(inSection: section))
    let combinedItemWidth = (numberOfItems * flowLayout.itemSize.width) + ((numberOfItems - 1)  * flowLayout.minimumInteritemSpacing)
    let padding = (collectionView.frame.width - combinedItemWidth) / 2
    return UIEdgeInsets(top: 0, left: padding, bottom: 0, right: padding)
}

এছাড়াও, যদি আপনি এখনও সমস্যার সম্মুখীন হন আপনি সেট নিশ্চিত করুন যে উভয় করতে minimumInteritemSpacingএবং minimumLineSpacingএকই মান যেহেতু এই মান পারস্পরিক সম্পর্কযুক্ত বলে মনে হচ্ছে।

UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
flowLayout.minimumInteritemSpacing = 20.0;
flowLayout.minimumLineSpacing = 20.0;

আমার জন্য কেবল ক্র্যাশ হয়েছে
সুপারটেকনবফ

ObjC অবজেক্টে ভিউলআউট সরাসরি ব্যবহার করা হয়। আইটেম সাইজ এবং ন্যূনতম অন্তঃসত্ত্বা স্পেসিং অ্যাক্সেস করতে সক্ষম হওয়ার জন্য এটি অবশ্যই ইউআইকোলিকেশনভিউফ্লোএলয়েটে কাস্ট করা উচিত
বাটিসিএমডি

19

এটি আপনার সংগ্রহ দর্শন প্রতিনিধিতে রাখুন। এটি অন্যান্য উত্তরের তুলনায় মৌলিক ফ্লো লেআউট সেটিংসকে বেশি বিবেচনা করে এবং এর ফলে আরও জেনেরিক।

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    NSInteger cellCount = [collectionView.dataSource collectionView:collectionView numberOfItemsInSection:section];
    if( cellCount >0 )
    {
        CGFloat cellWidth = ((UICollectionViewFlowLayout*)collectionViewLayout).itemSize.width+((UICollectionViewFlowLayout*)collectionViewLayout).minimumInteritemSpacing;
        CGFloat totalCellWidth = cellWidth*cellCount + spacing*(cellCount-1);
        CGFloat contentWidth = collectionView.frame.size.width-collectionView.contentInset.left-collectionView.contentInset.right;
        if( totalCellWidth<contentWidth )
        {
            CGFloat padding = (contentWidth - totalCellWidth) / 2.0;
            return UIEdgeInsetsMake(0, padding, 0, padding);
        }
    }
    return UIEdgeInsetsZero;
}

সুইফ্ট সংস্করণ (ধন্যবাদ g0ld2k):

extension CommunityConnectViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {

    // Translated from Objective-C version at: http://stackoverflow.com/a/27656363/309736

        let cellCount = CGFloat(viewModel.getNumOfItemsInSection(0))

        if cellCount > 0 {
            let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
            let cellWidth = flowLayout.itemSize.width + flowLayout.minimumInteritemSpacing
            let totalCellWidth = cellWidth*cellCount + spacing*(cellCount-1)
            let contentWidth = collectionView.frame.size.width - collectionView.contentInset.left - collectionView.contentInset.right

            if (totalCellWidth < contentWidth) {
                let padding = (contentWidth - totalCellWidth) / 2.0
                return UIEdgeInsetsMake(0, padding, 0, padding)
            }
        }

        return UIEdgeInsetsZero
    }
}

4
প্রকৃতপক্ষে আপনার ইউআইসিকলিকেশনভিউডেলিগেটফ্লোএলআউটে। ধন্যবাদ, এটি এমন একক কক্ষের জন্য কাজ করে যা এক সারি বা একাধিক সারি। অন্যান্য উত্তর কিছু না।
জিন ডি লিসা

4
এটিকে সুইফটে রূপান্তরিত করে এটি দুর্দান্ত কাজ করে! সুইফট সংস্করণ এখানে উপলব্ধ ।
g0ld2k

4
এটি বেশ সঠিক নয়, totalCellWidthহওয়া উচিত cellWidth*cellCount + spacing*(cellCount-1)
জেমস পি

4
এই "সমাধানগুলি" একাধিক চেষ্টা করার পরে এই কেবলমাত্র আমিই swift3.0 এর জন্য কিছুটা পরিবর্তন করার পরে সঠিকভাবে কাজ করতে সক্ষম হয়েছি
কেমিকোফা ভূত

@ অরগদিয়ালার আপনি কি আপনার সুইফট 3 পরিবর্তনগুলি প্রতিফলিত করার জন্য উত্তরটি পরিবর্তন করতে চান?
বার্ট

11

স্থির আকারের সংগ্রহ ভিউ সেলগুলির জন্য আমার সমাধান যা বাম এবং ডানদিকে প্যাডিং প্রয়োজন need

func collectionView(collectionView: UICollectionView, 
layout collectionViewLayout: UICollectionViewLayout, 
insetForSectionAtIndex section: Int) -> UIEdgeInsets {

    let flowLayout = (collectionViewLayout as! UICollectionViewFlowLayout)
    let cellSpacing = flowLayout.minimumInteritemSpacing
    let cellWidth = flowLayout.itemSize.width
    let cellCount = CGFloat(collectionView.numberOfItemsInSection(section))

    let collectionViewWidth = collectionView.bounds.size.width

    let totalCellWidth = cellCount * cellWidth
    let totalCellSpacing = cellSpacing * (cellCount - 1)

    let totalCellsWidth = totalCellWidth + totalCellSpacing

    let edgeInsets = (collectionViewWidth - totalCellsWidth) / 2.0

    return edgeInsets > 0 ? UIEdgeInsetsMake(0, edgeInsets, 0, edgeInsets) : UIEdgeInsetsMake(0, cellSpacing, 0, cellSpacing)
}

9

আমার অ্যাপটিতে আমার একটি ট্যাগ বার রয়েছে যা একটি UICollectionView& স ব্যবহার করে UICollectionViewFlowLayout, একক সারির ঘর কেন্দ্র প্রান্তিকিত।

সঠিক ইনডেন্টটি পেতে, আপনি আপনার প্রস্থ থেকে সমস্ত কক্ষের মোট প্রস্থ (স্পেসিং সহ) বিয়োগ করুন UICollectionViewএবং দুটি দ্বারা বিভাজন করুন।

[........Collection View.........]
[..Cell..][..Cell..]
                   [____indent___] / 2

=

[_____][..Cell..][..Cell..][_____]

সমস্যাটি হ'ল এই ফাংশনটি -

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

আগে বলা হয় ...

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;

... যাতে আপনি মোট প্রস্থ নির্ধারণ করতে আপনার ঘরগুলি দিয়ে পুনরাবৃত্তি করতে পারবেন না।

পরিবর্তে আপনাকে আবার প্রতিটি ঘরের প্রস্থ গণনা করতে হবে, আমার ক্ষেত্রে আমি ব্যবহার করি [NSString sizeWithFont: ... ]আমার ঘরের প্রস্থগুলি ইউআইএবেল নিজেই নির্ধারিত হয়।

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    CGFloat rightEdge = 0;
    CGFloat interItemSpacing = [(UICollectionViewFlowLayout*)collectionViewLayout minimumInteritemSpacing];

    for(NSString * tag in _tags)
        rightEdge += [tag sizeWithFont:[UIFont systemFontOfSize:14]].width+interItemSpacing;

    // To center the inter spacing too
    rightEdge -= interSpacing/2;

    // Calculate the inset
    CGFloat inset = collectionView.frame.size.width-rightEdge;

    // Only center align if the inset is greater than 0
    // That means that the total width of the cells is less than the width of the collection view and need to be aligned to the center.
    // Otherwise let them align left with no indent.

    if(inset > 0)
        return UIEdgeInsetsMake(0, inset/2, 0, 0);
    else
        return UIEdgeInsetsMake(0, 0, 0, 0);
}

আপনি কিভাবে পাবেন interSpacing?
ড্রুक्स

interSpacingশুধু আমার কোডে একটি ধ্রুবক, যে UICollectionViewCells মধ্যে স্থান আমি নির্ধারণ করে
Sion

4
তবে এই স্থানটি পৃথক হতে পারে: FWIK আপনি কেবল ন্যূনতম মান ধরে / নিতে পারবেন।
ড্রাক্স

8

সুইফটে, নীচেরগুলি প্রতিটি ঘরের পাশের প্যাডিংয়ের সঠিক পরিমাণ প্রয়োগ করে সমানভাবে সেল বিতরণ করবে। অবশ্যই আপনাকে প্রথমে আপনার ঘরের প্রস্থটি জানতে / সেট করতে হবে।

func collectionView(collectionView: UICollectionView,
    layout collectionViewLayout: UICollectionViewLayout,
    insetForSectionAtIndex section: Int) -> UIEdgeInsets {

        var cellWidth : CGFloat = 110;

        var numberOfCells = floor(self.view.frame.size.width / cellWidth);
        var edgeInsets = (self.view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1);

        return UIEdgeInsetsMake(0, edgeInsets, 60.0, edgeInsets);
}

সারি ব্যবধান যুক্ত করতে, 60.0 এর পরিবর্তে 0 টি পরিবর্তন করুন
অস্কার ক্যাথেলন

8

সুইফট 2.0 আমার জন্য কাজ করে!

 func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
        let edgeInsets = (screenWight - (CGFloat(elements.count) * 50) - (CGFloat(elements.count) * 10)) / 2
        return UIEdgeInsetsMake(0, edgeInsets, 0, 0);
    }

যেখানে: স্ক্রিনওয়েট : মূলত এটি আমার সংগ্রহের প্রস্থ (পূর্ণ স্ক্রিনের প্রস্থ) - আমি স্থির করে রেখেছি: স্ক্রিনউইট: সিজিফ্লোট = ইউআইএস স্ক্রিন.মাইনস্ক্রিন () সীমানা.উইথথ কারণ সেলফ.ভিউ.বাউন্ডস প্রতিবার 600 - কোজ সাইজের শ্রেণীর উপাদান দেখায় - 50 টি কক্ষের অ্যারে - আমার ম্যানুয়াল কক্ষের প্রস্থ 10 - কক্ষগুলির মধ্যে আমার দূরত্ব


4
আপনি screenWight পরিবর্তে collectionView.frame.size.width ব্যবহার করতে পারে, শুধু যদি আপনি UICollectionView আকার পরিবর্তন করতে চান
অস্কার


2

এটি এক্সকোড 5-এ নতুন কিনা তা নিশ্চিত নয় তবে আপনি এখন ইন্টারফেস বিল্ডারের মাধ্যমে আকার পরিদর্শকটি খুলতে পারেন এবং সেখানে একটি ইনসেট সেট করতে পারেন। এটি আপনাকে এটি করার জন্য কাস্টম কোড লিখতে বাধা দেবে এবং আপনি যথাযথ অফসেটগুলি খুঁজে পান সেই গতিটি খুব দ্রুত বাড়িয়ে তুলবে।


1

এটি করার আরেকটি উপায় হ'ল সেটিংটি সেট করা collectionView.center.x, এটির মতো:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if let
        collectionView = collectionView,
        layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
    {
        collectionView.center.x = view.center.x + layout.sectionInset.right / 2.0
    }
}

এই ক্ষেত্রে, শুধুমাত্র সঠিক ইনসেটটি সম্মান করা যা আমার পক্ষে কাজ করে।


1

ব্যবহারকারীর উপর ভিত্তি করে 3676011 উত্তর, আমি ছোট সংশোধন আরও বিশদ একটি প্রস্তাব করতে পারেন। এই সমাধানটি সুইফট ২.০ এ দুর্দান্ত কাজ করে ।

enum CollectionViewContentPosition {
    case Left
    case Center
}

var collectionViewContentPosition: CollectionViewContentPosition = .Left

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
    insetForSectionAtIndex section: Int) -> UIEdgeInsets {

    if collectionViewContentPosition == .Left {
        return UIEdgeInsetsZero
    }

    // Center collectionView content

    let itemsCount: CGFloat = CGFloat(collectionView.numberOfItemsInSection(section))
    let collectionViewWidth: CGFloat = collectionView.bounds.width

    let itemWidth: CGFloat = 40.0
    let itemsMargin: CGFloat = 10.0

    let edgeInsets = (collectionViewWidth - (itemsCount * itemWidth) - ((itemsCount-1) * itemsMargin)) / 2

    return UIEdgeInsetsMake(0, edgeInsets, 0, 0)
}

একটি সমস্যা ছিল

(সিজিফ্লোট (এলিমেন্টস কাউন্ট) * 10))

অতিরিক্ত -1উল্লেখ করা উচিত যেখানে ।


1

এইভাবেই আমি একটি সংগ্রহের ভিউ পেয়েছি যা একটি নির্দিষ্ট ইন্টারাইটেম স্পেসিংয়ের মধ্যবর্তী স্থানে ছিল

#define maxInteritemSpacing 6
#define minLineSpacing 3

@interface MyFlowLayout()<UICollectionViewDelegateFlowLayout>

@end

@implementation MyFlowLayout

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.minimumInteritemSpacing = 3;
        self.minimumLineSpacing = minLineSpacing;
        self.scrollDirection = UICollectionViewScrollDirectionVertical;
    }
    return self;
}

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

    if (answer.count > 0) {
        NSMutableArray<NSMutableArray<UICollectionViewLayoutAttributes *> *> *rows = [NSMutableArray array];
        CGFloat maxY = -1.0f;
        NSInteger currentRow = 0;

        //add first item to row and set its maxY
        [rows addObject:[@[answer[0]] mutableCopy]];
        maxY = CGRectGetMaxY(((UICollectionViewLayoutAttributes *)answer[0]).frame);

        for(int i = 1; i < [answer count]; ++i) {
            //handle maximum spacing
            UICollectionViewLayoutAttributes *currentLayoutAttributes = answer[i];
            UICollectionViewLayoutAttributes *prevLayoutAttributes = answer[i - 1];
            NSInteger maximumSpacing = maxInteritemSpacing;
            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;
            }

            //handle center align
            CGFloat currentY = currentLayoutAttributes.frame.origin.y;
            if (currentY >= maxY) {
                [self shiftRowToCenterForCurrentRow:rows[currentRow]];

                //next row
                [rows addObject:[@[currentLayoutAttributes] mutableCopy]];
                currentRow++;
            }
            else {
                //same row
                [rows[currentRow] addObject:currentLayoutAttributes];
            }

            maxY = MAX(CGRectGetMaxY(currentLayoutAttributes.frame), maxY);
        }

        //mark sure to shift 1 row items
        if (currentRow == 0) {
            [self shiftRowToCenterForCurrentRow:rows[currentRow]];
        }
    }

    return answer;
}

- (void)shiftRowToCenterForCurrentRow:(NSMutableArray<UICollectionViewLayoutAttributes *> *)currentRow
{
    //shift row to center
    CGFloat endingX = CGRectGetMaxX(currentRow.lastObject.frame);
    CGFloat shiftX = (self.collectionViewContentSize.width - endingX) / 2.f;
    for (UICollectionViewLayoutAttributes *attr in currentRow) {
        CGRect shiftedFrame = attr.frame;
        shiftedFrame.origin.x += shiftX;
        attr.frame = shiftedFrame;
    }
}

@end

1

সোয়েফ্ট ৩.০ ব্যবহার করে কেগাইডিসের অবজেক্টিভ সি উত্তরের কার্যকারী সংস্করণ:

let flow = UICollectionViewFlowLayout()

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {        
    let numberOfItems = collectionView.numberOfItems(inSection: 0)
    let combinedItemWidth:CGFloat = (CGFloat(numberOfItems) * flow.itemSize.width) + ((CGFloat(numberOfItems) - 1) * flow.minimumInteritemSpacing)
    let padding = (collectionView.frame.size.width - combinedItemWidth) / 2

    return UIEdgeInsetsMake(0, padding, 0, padding)
}

1

কয়েকটি অনুমান সহ আমার সমাধান এখানে:

  • একটি মাত্র বিভাগ আছে
  • বাম এবং ডান insets সমান
  • ঘরের উচ্চতা সমান

আপনার প্রয়োজন মেটাতে নির্দ্বিধায়

ভেরিয়েবল সেল প্রস্থ সহ কেন্দ্রের বিন্যাস:

protocol HACenteredLayoutDelegate: UICollectionViewDataSource {
    func getCollectionView() -> UICollectionView
    func sizeOfCell(at index: IndexPath) -> CGSize
    func contentInsets() -> UIEdgeInsets
}

class HACenteredLayout: UICollectionViewFlowLayout {
    weak var delegate: HACenteredLayoutDelegate?
    private var cache = [UICollectionViewLayoutAttributes]()
    private var contentSize = CGSize.zero
    override var collectionViewContentSize: CGSize { return self.contentSize }

    required init(delegate: HACenteredLayoutDelegate) {
        self.delegate = delegate
        super.init()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func invalidateLayout() {
        cache.removeAll()
        super.invalidateLayout()
    }

    override func prepare() {
        if cache.isEmpty && self.delegate != nil && self.delegate!.collectionView(self.delegate!.getCollectionView(), numberOfItemsInSection: 0) > 0 {
            let insets = self.delegate?.contentInsets() ?? UIEdgeInsets.zero
            var rows: [(width: CGFloat, count: Int)] = [(0, 0)]
            let viewWidth: CGFloat = UIScreen.main.bounds.width
            var y = insets.top
            var unmodifiedIndexes = [IndexPath]()
            for itemNumber in 0 ..< self.delegate!.collectionView(self.delegate!.getCollectionView(), numberOfItemsInSection: 0) {
                let indexPath = IndexPath(item: itemNumber, section: 0)
                let cellSize = self.delegate!.sizeOfCell(at: indexPath)
                let potentialRowWidth = rows.last!.width + (rows.last!.count > 0 ? self.minimumInteritemSpacing : 0) + cellSize.width + insets.right + insets.left
                if potentialRowWidth > viewWidth {
                    let leftOverSpace = max((viewWidth - rows[rows.count - 1].width)/2, insets.left)
                    for i in unmodifiedIndexes {
                        self.cache[i.item].frame.origin.x += leftOverSpace
                    }
                    unmodifiedIndexes = []
                    rows.append((0, 0))
                    y += cellSize.height + self.minimumLineSpacing
                }
                unmodifiedIndexes.append(indexPath)
                let attribute = UICollectionViewLayoutAttributes(forCellWith: indexPath)
                rows[rows.count - 1].count += 1
                rows[rows.count - 1].width += rows[rows.count - 1].count > 1 ? self.minimumInteritemSpacing : 0
                attribute.frame = CGRect(x: rows[rows.count - 1].width, y: y, width: cellSize.width, height: cellSize.height)
                rows[rows.count - 1].width += cellSize.width
                cache.append(attribute)
            }
            let leftOverSpace = max((viewWidth - rows[rows.count - 1].width)/2, insets.left)
            for i in unmodifiedIndexes {
                self.cache[i.item].frame.origin.x += leftOverSpace
            }
            self.contentSize = CGSize(width: viewWidth, height: y + self.delegate!.sizeOfCell(at: IndexPath(item: 0, section: 0)).height + insets.bottom)
        }
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var layoutAttributes = [UICollectionViewLayoutAttributes]()

        for attributes in cache {
            if attributes.frame.intersects(rect) {
                layoutAttributes.append(attributes)
            }
        }
        return layoutAttributes
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        if indexPath.item < self.cache.count {
            return self.cache[indexPath.item]
        }
        return nil
    }
}

ফলাফল:

এখানে চিত্র বর্ণনা লিখুন


0

আপনি এটি কীভাবে করতে পারেন তা এখানে রয়েছে এবং এটি দুর্দান্ত কাজ করে

func refreshCollectionView(_ count: Int) {
    let collectionViewHeight = collectionView.bounds.height
    let collectionViewWidth = collectionView.bounds.width
    let numberOfItemsThatCanInCollectionView = Int(collectionViewWidth / collectionViewHeight)
    if numberOfItemsThatCanInCollectionView > count {
        let totalCellWidth = collectionViewHeight * CGFloat(count)
        let totalSpacingWidth: CGFloat = CGFloat(count) * (CGFloat(count) - 1)
        // leftInset, rightInset are the global variables which I am passing to the below function
        leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2;
        rightInset = -leftInset
    } else {
        leftInset = 0.0
        rightInset = -collectionViewHeight
    }
    collectionView.reloadData()
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.