ios - 在 UICollectionView 中为单元格设置边界和调整大小

标签 ios swift swift2 uicollectionview uicollectionviewcell

如图

screen shot

我将基于 UIViewController 实现一个 UICollectionView

这是我的代码:

class SettingViewController: BaseViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    @IBOutlet var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 3
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 3
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! SettingCollectionViewCell
        cell.backgroundColor = UIColor.greenColor()
        cell.lb.text = "Something"
        cell.img.image = UIImage(named: "setting")
        cell.layer.borderColor = UIColor.lightGrayColor().CGColor
        cell.layer.borderWidth = 1
        return cell;
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        let screen = UIScreen.mainScreen().bounds
        return CGSize(width: CGFloat(screen.width/3 - 10), height: 120)
    }
}

这是结果:

result :)))

我真的疯了!
我实现了 func sizeForItemAtIndexPath 来调整单元格的大小,但我得到的只是每个单元格之间的间距,它甚至没有相同的宽度,而且我不知道如何在设计中获得边框。

请帮帮我!

最佳答案

这里的技巧是,我们需要创建自定义 UICollectionViewFlowLayout 为:

CustomCollectionLayout.h

#import <UIKit/UIKit.h>

@protocol CustomCollectionLayoutDelegate      
<UICollectionViewDelegateFlowLayout>

@end

@interface CustomCollectionLayout : UICollectionViewFlowLayout
@end

CustomCollectionLayout.m

#import "CustomCollectionLayout.h"

@interface CustomCollectionLayout ()

@end

@implementation CustomCollectionLayout
{
    NSDictionary *_layoutInfo;
    CGFloat maxColumnHeight;
    __weak id<CustomCollectionLayoutDelegate> delegate;
}

- (void)prepareLayout{

    delegate = (id<CustomCollectionLayoutDelegate>) self.collectionView.delegate;
    //Calculate max values
    maxColumnHeight = [self maxColumnHeight];

    //Store calculated frames for cells in the dictionary
    NSMutableDictionary *cellLayoutInfo = [NSMutableDictionary dictionary];

    //Calculate Frame for a cell, per values from DataSource
    CGFloat originY = 0;
    NSInteger sectionCount = [self.collectionView numberOfSections];

    for (NSInteger section = 0; section < sectionCount; section++) {

        UIEdgeInsets itemInsets = UIEdgeInsetsZero;
        if ([delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
            itemInsets = [delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:section];
            originY += itemInsets.top;
        }

        CGFloat height = 0;
        NSInteger itemCount = [self.collectionView numberOfItemsInSection:section];
        CGFloat originX = itemInsets.left;

        for (NSInteger item = 0; item < itemCount; item++) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:section];

            UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
            CGSize itemSize = CGSizeZero;
            if ([delegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:)]) {
                itemSize = [delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
                float selectedOriginY = originY;
                itemAttributes.frame = CGRectMake(originX, selectedOriginY, itemSize.width, itemSize.height);
            }
            cellLayoutInfo[indexPath] = itemAttributes;

            CGFloat interItemSpacingX = 0;
            if ([delegate respondsToSelector:@selector(collectionView:layout:minimumInteritemSpacingForSectionAtIndex:)]) {
                interItemSpacingX = [delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:section];
            }

            originX += floorf(itemSize.width + interItemSpacingX);
            height = height > itemSize.height ? height : itemSize.height;
        }

        CGFloat interItemSpacingY = 0;
        if ([delegate respondsToSelector:@selector(collectionView:layout:minimumLineSpacingForSectionAtIndex:)]) {
            interItemSpacingY = [delegate collectionView:self.collectionView layout:self minimumLineSpacingForSectionAtIndex:section];
        }

        originY += floor(height + interItemSpacingY);
    }

    _layoutInfo = cellLayoutInfo;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:_layoutInfo.count];

    [_layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath,
                                                     UICollectionViewLayoutAttributes *attributes,
                                                     BOOL *innerStop) {
        if (CGRectIntersectsRect(rect, attributes.frame)) {
            [allAttributes addObject:attributes];
        }
    }];

    return allAttributes;
}

- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound
{
    return YES;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return _layoutInfo[indexPath];
}

- (CGSize)collectionViewContentSize
{
    CGFloat width = self.collectionView.frame.size.width;
    CGFloat height = maxColumnHeight;
    return CGSizeMake(width, height);
}

//Maximum Height of perticular Column in CollectionView
- (CGFloat)maxColumnHeight
{
    NSInteger sectionCount = [self.collectionView numberOfSections];
    CGFloat maxHeight = 0;
    for (NSInteger section = 0; section < sectionCount; section++) {
        NSInteger itemCount = [self.collectionView numberOfItemsInSection:section];
        CGFloat maxRowHeight = 0;
        for (NSInteger item = 0; item < itemCount; item++) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:item inSection:section];
            if ([delegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:)]) {
                CGSize itemSize = [delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
                maxRowHeight = itemSize.height > maxRowHeight ? itemSize.height : maxRowHeight;
            }
        }
        CGFloat interSectionSpacingY = 0;
        if ([delegate respondsToSelector:@selector(collectionView:layout:minimumLineSpacingForSectionAtIndex:)]) {
            interSectionSpacingY = [delegate collectionView:self.collectionView layout:self minimumLineSpacingForSectionAtIndex:section];
        }

        UIEdgeInsets itemInsets = UIEdgeInsetsZero;
        if ([delegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]) {
            itemInsets = [delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:section];
        }

        maxHeight += maxRowHeight;

        //Add interSectionSpacing and Insets for all sections except last.
        if (section != sectionCount-1) {
            maxHeight += interSectionSpacingY + itemInsets.top;
        }
    }

    return maxHeight;
}

@end

请原谅我提供Objective-C代码,但我们可以使用Bridging Header

然后将此自定义布局用作:

enter image description here 灰色是 Collection View ,粉色是单元格。

委托(delegate)方法:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionCellId", forIndexPath: indexPath)
    cell.backgroundColor = UIColor.greenColor()
    //cell.lb.text = "Something"
    //cell.img.image = UIImage(named: "setting")
    cell.layer.borderColor = UIColor.lightGrayColor().CGColor
    cell.layer.borderWidth = 1
    return cell;
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let screen = UIScreen.mainScreen().bounds
    return CGSize(width: CGFloat(screen.width/3), height: 120)
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
    return 0
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
    return 0
}

这是输出:
enter image description here

现在,我们可以使用任何自定义单元格并获得所需的外观。

希望对您有所帮助!

关于ios - 在 UICollectionView 中为单元格设置边界和调整大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38772537/

相关文章:

ios - 如何在只有全名的情况下使用姓氏对核心数据进行排序?

ios - 从由UILabel激活的键盘获取输入

objective-c - 如何从网站动态获取数据并将其添加到 iPhone 应用程序?

ios - 同时运行 Collection View 和 TableView 时应用程序崩溃。崩溃 :fatal error: unexpectedly found nil while unwrapping an Optional value

Swift 通用 bool 类型转换不同于直接类型转换

Swift:无法在协议(protocol)扩展中使用变异方法

ios - reloadData 不会将完成处理程序的 dispatch_async 中的 TableView 重新加载到主线程

ios - 什么时候为 NSDateFormatter 设置 NSLocale ?

ios - Swift:类AppDelegate中的线程1信号SIGABRT:UIResponder,UIApplicationDelegate

swift - 根据 bool 属性对数组进行排序