在UICollectionView中对单元格进行边框化和调整大小

时间:2016-08-04 16:15:12

标签: ios swift swift2 uicollectionview uicollectionviewcell

如图所示

screen shot

我将基于UICollectionView实施UIViewController

这是我的代码:

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来调整单元格的大小,但我得到的只是每个单元格之间的间距,它甚至没有相同的宽度,我不知道如何在设计中获得边框。

请帮助我!

2 个答案:

答案 0 :(得分:0)

这里的诀窍是,我们需要创建自定义 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代码,但我们可以使用桥接标题

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

enter image description here 灰色是集合视图,粉红色是单元格。

委托方法:

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

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

希望这会对你有帮助!

答案 1 :(得分:-1)

自我调整单元格实现以下两种方法:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("hobbiesCell", forIndexPath: indexPath) as! HobbiesTagCell
        self.configureCell(cell, forIndexPath: indexPath)
        return cell
    } 

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        self.configureCell(self.sizingCell!, forIndexPath: indexPath)
        return self.sizingCell!.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
    }

在单元格之间的相等空间实现此自定义流程布局:

class CustomViewFlowLayout : UICollectionViewFlowLayout {

    let cellSpacing:CGFloat = 2

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