如果浮点大小,则会出现奇怪的UICollectionViewCell行为

时间:2017-07-27 08:18:07

标签: ios objective-c uicollectionview uicollectionviewcell calayer

更新 示例项目为github link

使用iPHONE 6模拟器

实现此错误的2种可能方法。 只需构建并运行并查看。 或取消注释256行

//return CGSizeMake(widthAndHeight * self.venueLayoutZoom, widthAndHeight * self.venueLayoutZoom);

并按"删除列"按钮

UICollectionView有很多UICollectionViewCell个。我的UI让我在单元格之间使用零空间。我的pinch中有一个UICollectionView手势。所以有时候sizeForItem:atIndexPath:会给我一个大的浮点数(比如11.821123411231)。问题是: 如果我不绕过这些花车我有时会有一种奇怪的行为 - enter image description here

应为enter image description here

如果我向上或向下舍入sizeForItem:atIndexPath:它看起来很棒但是单元格之间有空格enter image description here

我不知道该怎么做。没有这些空间或奇怪的细胞是非常必要的。 我的流程布局为this

控制器代码

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
    CGFloat widthAndHeight = [self widthAndHeightForCollectionView:collectionView];
    CGFloat result = widthAndHeight * self.venueLayoutZoom;
    return CGSizeMake(result, result);
}

- (void)didReceivePinchGesture:(UIPinchGestureRecognizer *)gesture
{
    static CGFloat scaleStart;

    if (gesture.state == UIGestureRecognizerStateBegan) {
        scaleStart = self.venueLayoutZoom;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged) {

        self.venueLayoutZoom = scaleStart * gesture.scale;
    }
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    VenueLayoutCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kVenueLayoutCellReuseIdentifier forIndexPath:indexPath];

    self.activeCollectionViewCellsDictionary[indexPath] = cell;
    if (self.activeCollectionViewObjects.count > indexPath.section) {
        NSArray *rows = self.activeCollectionViewObjects[indexPath.section];
        if (rows.count > indexPath.row) {
            if ([rows[indexPath.row] isKindOfClass:[VenueLayoutCellObject class]]) {
                VenueLayoutCellObject *object = rows[indexPath.row];
                cell.cellObject = object;

            }
        }
    }
    return cell;
}

细胞代码:

@property (nonatomic, strong) CALayer *circularLayer;

- (void)awakeFromNib
{
    [super awakeFromNib];
    [self allocAndAddLayers];
}

- (void)allocAndAddLayers
{
    self.circularLayer = [CALayer layer];
    [self.layer addSublayer:self.circularLayer];
}

#pragma mark - Property Set

- (void)setCellObject:(VenueLayoutCellObject *)cellObject
{
    self->_cellObject = cellObject;
    self.objectBackgroundColor = cellObject.objectColor;
    self.type = cellObject.type;
}

- (void)prepareForReuse
{
    [self.circularLayer removeFromSuperlayer];
    [self allocAndAddLayers];
}

- (void)setType:(VenueLayoutObjectType)type
{
    self->_type = type;
    [self updateInderfaceDependOnType];
}

- (void)layoutSubviews
{
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    [self updateRoundedCorners];
    [CATransaction commit];
    [super layoutSubviews];
}

- (void)updateRoundedCorners
{
    CGRect bounds = self.bounds;
    CGRect frame = self.frame;
    self.circularLayer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
}

- (void)setLayerBackgroundColor:(UIColor *)color
{
    self.circularLayer.backgroundColor = color.CGColor;
    self.objectMaskLayer.strokeColor = color.CGColor;
    self.deselectedColor = color;
}

- (void)updateInderfaceDependOnType
{
    UIColor *tempObjectColor = [UIColor grayColor];
    UIColor *objectColor = self.objectBackgroundColor ? : tempObjectColor;
    [self setLayerBackgroundColor:objectColor];
}

更新代码:

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
    CGFloat widthAndHeight = self.widthAndHeightForActiveCollectionView;
    CGFloat result = lroundf(widthAndHeight * self.venueLayoutZoom);
    CGFloat width = result;
    if (indexPath.row > self.increasedWidthInitialIndex) {
        width++;
    }
    return CGSizeMake(width, result);
}

CGFloat widthAndHeight = CGRectGetWidth(self.activeCollectionView.bounds) / maxCount;
    NSNumber *widthNumber = @(CGRectGetWidth(self.activeCollectionView.bounds));
    NSInteger count = widthNumber.integerValue % maxCount;
    maxCount--;
    self.increasedWidthInitialIndex = maxCount - count;

更新 如果我使用较小的项目大小(例如CGSizeMake(7.f, 7.f)),则单元格不适合整体 集合视图但空间仍然存在

1 个答案:

答案 0 :(得分:1)

最终将宽度/高度设置为半像素会根据设备像素深度(视网膜与非视网膜)改变比例 - 更多信息here

当您尝试将屏幕划分为非整数时,即屏幕宽度为320时,创建6个53.3的单元格可能会导致UI中断。

你应该试着找到你的剩余部分,即:

320 % 6 -> 2

然后使2个单元格宽1像素。 因此,除了由53.3像素宽组成的6个单元格外,您将有2个由54个组成,另外还有53个由53个组成,然后一切都将正确匹配。

修改

在浏览完你的项目后,我添加了你的收藏品的打印输出,看看宽度可能导致什么问题,我在ViewController.m中添加了这个方法:

- (void)printoutGrid
{
    NSLog(@"collectionview bounds: %f, %@", self.activeCollectionView.bounds.size.width, NSStringFromCGSize(self.activeCollectionView.contentSize));
    CGFloat calculatedWidth = [self widthAndHeightForActiveCollectionViewItem];
    CGFloat result = floor(calculatedWidth * self.venueLayoutZoom);

    for (int rowAt = 0; rowAt < self.activeCollectionViewObjects.count; rowAt++)
    {
        NSArray* arrayAt = self.activeCollectionViewObjects[rowAt];
        NSString* rowString = @"|";

        for (int colAt = 0; colAt < arrayAt.count; colAt++)
        {
            if (colAt > self.increasedWidthInitialIndex)
            {
                rowString = [rowString stringByAppendingString:[NSString stringWithFormat:@"%d|", (int)result + 1]];
            }
            else
            {
                rowString = [rowString stringByAppendingString:[NSString stringWithFormat:@"%d|", (int)result]];
            }
        }

        NSLog(@"%@", rowString);
    }
}

每次重新加载集合或使布局无效后调用它,我发现只应该使用floor而不是lroundf。

此方法将帮助您调试未来的宽度。

但是,在完成你的项目设置之后,你的模拟器中出现了一些东西,我注意到它太大/超出规模而没有视网膜,我去了你的项目设置,看到你的项目不是视网膜兼容的 - 哪个表示用户界面不会使用Auto-Scaling - &gt;这意味着它将使用相同的分辨率(320 x 518)用于所有设备及其功能,它会延伸UI - 这意味着在iPhone 6中它会倍增它,并且拉伸被反分析,这导致这些所谓的空即使那里没有空间,也要在细胞之间留出空间。

您需要做的是转到您的项目设置 - &gt;通常向下滚动到“启动屏幕文件”并从列表中选择“LaunchScreen”:

enter image description here

这似乎解决了这个项目的问题。如果您有任何问题以及是否有效,请告诉我。

请注意 - 它需要您更改大小计算,因为分辨率会在“viewDidLayoutSubviews”之后再次更改,而不仅仅是在视图加载时。

祝你好运!