【问题标题】:Adding padding to first and last cell of UICollectionView向 UICollectionView 的第一个和最后一个单元格添加填充
【发布时间】:2026-02-17 06:30:01
【问题描述】:

我对 UICollectionViewFlowLayout 进行了子类化,以获得具有分页行为的水平 UICollectionView。只要 UICollectionViewCell 不是最后一个单元格的第一个,它就可以正常工作。图片附在下面。

除了以下之外,我还需要覆盖 UICollectionViewFlowLayout 中的某些内容吗?

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
CGFloat offSetAdjustment = MAXFLOAT;
CGFloat horizontalCenter = (CGFloat) (proposedContentOffset.x + (self.collectionView.bounds.size.width / 2.0));

CGRect targetRect = CGRectMake(proposedContentOffset.x,
                               0.0,
                               self.collectionView.bounds.size.width,
                               self.collectionView.bounds.size.height);

NSArray *array = [self layoutAttributesForElementsInRect:targetRect];
for (UICollectionViewLayoutAttributes *layoutAttributes in array)
{
    if(layoutAttributes.representedElementCategory == UICollectionElementCategoryCell)
    {
        CGFloat itemHorizontalCenter = layoutAttributes.center.x;
        if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offSetAdjustment))
        {
            offSetAdjustment = itemHorizontalCenter - horizontalCenter;
        }
    }
}

CGFloat nextOffset = proposedContentOffset.x + offSetAdjustment;

do {
    proposedContentOffset.x = nextOffset;
    CGFloat deltaX = proposedContentOffset.x - self.collectionView.contentOffset.x;
    CGFloat velX = velocity.x;

    if(deltaX == 0.0 || velX == 0 || (velX > 0.0 && deltaX > 0.0) || (velX < 0.0 && deltaX < 0.0))
    {
        break;
    }

    if(velocity.x > 0.0)
    {
        nextOffset += [self snapStep];
    }
    else if(velocity.x < 0.0)
    {
        nextOffset -= [self snapStep];
    }
} while ([self isValidOffset:nextOffset]);

proposedContentOffset.y = 0.0;

return proposedContentOffset;
}
    - (BOOL)isValidOffset:(CGFloat)offset
{
    return (offset >= [self minContentOffset] && offset <= [self maxContentOffset]);
}

- (CGFloat)minContentOffset
{
  return -self.collectionView.contentInset.left;
}

- (CGFloat)maxContentOffset
{
    return [self minContentOffset] + self.collectionView.contentSize.width -      self.itemSize.width;
}

- (CGFloat)snapStep
{
return self.itemSize.width + self.minimumLineSpacing;
}

任何指针/ cmets 都会很有用。

【问题讨论】:

  • 你可以使用UICollectionViewFlowLayoutUIEdgeInsets sectionInset属性。请参阅此post。另请参阅Using section inset上的 Apple 文档

标签: ios objective-c uicollectionview uicollectionviewcell uicollectionviewlayout


【解决方案1】:

您可以使用这段代码进行填充

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

    return UIEdgeInsets(top: 60, left: 0, bottom: 40, right: 0)
}

【讨论】:

    【解决方案2】:

    在设置集合视图的框架时,您可以将左侧和右侧的空间设置为等于您的填充。

    您可以在cellForItemAtIndexPath 中设置条件,如果它是第一个单元格或最后一个单元格,则相应地管理填充。就是这样。

    或者

    你可以设置你的collectionView的contentInset属性。

    例如,

    UICollectionView *cv; // your collectionView
    
    cv.contentInset = UIEdgeInsetsMake(0, 5, 0, 5);
    

    或者,您可以在情节提要中设置UICollectionView contentInset 以使其正常工作。

    【讨论】:

    • 啊,过去 30 分钟我一直在玩部分插图,从来没想过设置 UICollectionView 本身的插图。
    • 是的,设置 contentInset 对您的情况来说是一个很好的解决方案。 :)
    • contentInset 是有道理的,但是如果它是最后一个项目并且您附加另一个项目,则将它放在 cellForItemAtIndexPath 中效果不佳,因为如果您滚动到最后并添加了一个新项目, cellForItemAtIndexPath 通常会为新的最终项目调用,但不会为先前的最终项目再次调用。或者至少不能保证被调用。
    • 不,您不应该在 cellForItemAtIndexPath 中设置 contentinsett,而且我的回答中也没有这样说!
    【解决方案3】:

    接受的解决方案有效,但如果您启用了 paging,则集合视图分页会损坏

    对我来说,解决方案是使用:

    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
    }
    
    

    【讨论】:

      【解决方案4】:

      对于 Swift 5:

      在您的viewDidLoad 中,像这样设置contentInsetcontentInset 属性:

      self.collectionView.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5);
      

      【讨论】:

        【解决方案5】:

        您可以通过更改 Interface Builder 中的插图来实现。它们可以在 Size Inspector 中作为 Section Insets 找到:

        【讨论】:

        • 有什么方法可以通过代码设置吗?我找不到方法。
        • @Supertecnoboff 你在 Swift 中设置它,就像 Rbar 的回答一样:self.collectionView.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
        【解决方案6】:

        简单的你可以使用collectionview方法来设置UIEdgeInsets就像下面的方法。

        -(UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
        {
          return UIEdgeInsetsMake(0,10,0,10); // top, left, bottom, right
        }
        

        在这里你可以为第一个和最后一个单元格传递左侧空间和右侧空间的值,你也可以通过下面的方法提供两个单元格之间的最小空间

        - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
           return 5.0;
        }
        

        【讨论】:

        • 当我创建 UICollectionViewFlowLayout 的实例时,我已经在设置 ​​inset。所以它没有帮助, minimumInteritemSpacing 在这里没有用,因为我正在做水平滚动。你必须在这里使用 minimumLineSpacing 我已经在做。
        最近更新 更多