在非滚动UICollectionView中动态调整UICollectionViewCell的大小

时间:2015-01-24 23:25:55

标签: ios objective-c uicollectionview uicollectionviewcell uicollectionviewlayout

我在屏幕顶部有一个小的单行水平布局UICollectionView。它最多可包含6个项目。问题是我希望所有6个项目都可见而不滚动(此集合视图也将用于不允许滚动的Today扩展)。我想要做的是稍微减少单元大小和项目间距,以允许所有6个单元格适合。

基本上我试图避免这种情况:

enter image description here

我已经玩了一段时间,但我不知道如何接近它。我创建了一个方法,每次在集合视图中添加或删除项目时都会触发该方法,就在调用[self.collectionview reloadData]之前。

-(void)setupCollectionViewLayout{

     UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout*)self.buttonBarCollectionView.collectionViewLayout;

        //Figure out if cells are wider than screen
    CGFloat screenwidth = self.view.frame.size.width;

    CGFloat sectionInsetLeft = 10;
    CGFloat sectionInsetRight = 10;
    CGFloat minItemSpacing = flowLayout.minimumInteritemSpacing;
    CGSize  itemsize = CGSizeMake(58,58);
    CGFloat itemsizeWidth = itemsize.width;
    CGFloat totalWidth = sectionInsetLeft + sectionInsetRight +
                        (itemsizeWidth * _armedRemindersArray.count) +
                        (minItemSpacing * (_armedRemindersArray.count -2));


    CGFloat reductionAmount = itemsizeWidth;
    if (totalWidth > screenwidth) {


        while (totalWidth > screenwidth) {
            totalWidth = totalWidth - 1;
             reductionAmount = reductionAmount - 1;
        }


        CGSize newCellSize = CGSizeMake(reductionAmount, reductionAmount);
        flowLayout.itemSize = newCellSize;

    }

    else flowLayout.itemSize = itemsize;

}

结果就是这样。

enter image description here

不完全是我所期待的。它不仅将所有东西压在左边并且还添加了第二行,但我似乎也有一个细胞重用问题。说实话,我会使用静态单元格,如果它甚至是一个选项,但不幸的是,这似乎是不可能的。

我该怎么办?子类化UICollectionViewFlowLayout?这不是基本上与我在内置的流程布局做同样的事情吗?

编辑: Kujey的答案肯定更接近我的需要。我仍然有一个细胞重用问题。 enter image description here

3 个答案:

答案 0 :(得分:4)

Xcode提供了一个专为您的需求而设计的对象。它被称为UICollectionViewFlowLayout,你需要做的就是将它子类化并按照你想要的方式放置你的单元格。每次集合视图需要更新布局时,都会调用prepareForLayout函数。 您需要的代码如下:

#import "CustomLayout.h"

#define MainCell @"MainCell"

@interface CustomLayout ()

@property (nonatomic, strong) NSMutableDictionary *layoutInfo;

@end

@implementation CustomLayout


-(NSMutableDictionary *) layoutInfo
{
    if (!_layoutInfo) {
        _layoutInfo = [NSMutableDictionary dictionary];
    }

    return _layoutInfo;
}

-(void) prepareLayout
{
    NSMutableDictionary *cellLayoutInfo = [NSMutableDictionary dictionary];

    NSIndexPath *indexPath;

    CGFloat itemWidth;
    CGFloat itemSpacing;

    CGFloat widthWithoutSpacing = [self collectionViewContentSize].width / ([self.collectionView numberOfItemsInSection:0]);

    if (widthWithoutSpacing > [self collectionViewContentSize].height) {
        itemWidth = [self collectionViewContentSize].height;
        itemSpacing = ([self collectionViewContentSize].width - itemWidth*[self.collectionView numberOfItemsInSection:0])/
        ([self.collectionView numberOfItemsInSection:0]+1);
    }
    else {
        itemWidth = widthWithoutSpacing;
        itemSpacing = 0;
    }

    CGFloat xPosition = itemSpacing;

    for (NSInteger section = 0; section < [self.collectionView numberOfSections]; section++) {

        for (NSInteger index = 0 ; index < [self.collectionView numberOfItemsInSection:section] ; index++) {

            indexPath = [NSIndexPath indexPathForItem:index inSection:section];
            UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

            CGRect currentFrame=itemAttributes.frame;

            currentFrame.origin.x = xPosition;
            currentFrame.size.width = itemWidth;
            currentFrame.size.height = itemWidth;

            itemAttributes.frame=currentFrame;
            cellLayoutInfo[indexPath] = itemAttributes;

            xPosition += itemWidth + itemSpacing;
        }
    }

    self.layoutInfo[MainCell] = cellLayoutInfo;
}


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


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

    [self.layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSString *elementIdentifier, NSDictionary *elementsInfo, BOOL *stop) {
        [elementsInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath, UICollectionViewLayoutAttributes *attributes, BOOL *innerStop) {
            if (CGRectIntersectsRect(rect, attributes.frame)) {
                [allAttributes addObject:attributes];
            }
        }];
    }];

    return allAttributes;
}


-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return self.layoutInfo[MainCell][indexPath];
}


-(CGSize) collectionViewContentSize
{
    return self.collectionView.frame.size;
}



@end

如果需要垂直居中,也可以更改单元格的y原点。

答案 1 :(得分:0)

尝试使用此代码。我得到宽度并使用_armedRemindersArray(我猜你使用这个数组作为项目。)

-(void)setupCollectionViewLayout{   
         UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout*)self.buttonBarCollectionView.collectionViewLayout;

         //Figure out if cells are wider than screen
         CGFloat screenwidth = self.view.frame.size.width;
         CGFloat width = screenwidth - ((sectionInsetLeft + sectionInsetRight) *_armedRemindersArray.count  + minItemSpacing * (_armedRemindersArray.count -2));
         CGSize  itemsize = CGSizeMake(width,width);
         flowLayout.itemSize = itemsize;
}

答案 2 :(得分:0)

我不知道你为什么先设置itemsize然后减少它。我认为你应该反过来做这件事:

-(void)setupCollectionViewLayout{

     UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout*)self.buttonBarCollectionView.collectionViewLayout;

    CGFloat sectionInsetLeft = 10;
    CGFloat sectionInsetRight = 10;
    CGFloat minItemSpacing = flowLayout.minimumInteritemSpacing;

    // Find the appropriate item width (<= 58)
    CGFloat screenwidth = self.view.frame.size.width;
    CGFloat itemsizeWidth = (screenwidth - sectionInsetLeft - sectionInsetRight - (minItemSpacing * (_armedRemindersArray.count -2))) / _armedRemindersArray.count
    itemsizeWidth = itemsizeWidth > 58 ? 58 : itemsizeWidth;

    flowLayout.itemSize = CGSizeMake(itemsizeWidth, itemsizeWidth);
}

这有用吗?如果没有,请您提供更多代码?