流式布局中UICollectionView单元格边框

4
我正在使用UICollectionView来布局一堆以标题首字母分组的单元格。每个单元格应该有非常细的边框,而各个部分的标题应该在顶部和底部有边框。这是我的当前原型:
[图片]
我通过以下规则实现当前外观:
1. 描边每个单元格的右侧和底部边缘。 2. 描边每个部分标题的底部边缘。
这很接近我想要的效果,但有两个问题:
1. 如果一个部分标题前面的行没有填满,则标题上方的边框会在屏幕右侧停止之前截断。 2. 在此屏幕截图中无法看到,但如果一行是满的,在最后一个单元格的右边仍会绘制边框,这看起来有点奇怪。
我想修复这个问题的最佳想法是告诉每个单元格它是否在部分的最后一行或者是否是一行中的最后一个单元格; 然后单元格将关闭有问题的边框,部分标题将画出顶部边框和底部边框,就可以一切顺利了。不过我不知道如何实现。
对于如何解决这个问题,或者有没有其他方法可以达到我想要的外观,有什么想法吗?我目前正在使用UICollectionViewFlowLayout。
3个回答

4
我最终通过子类化UICollectionViewFlowLayout,在流式布局计算出每个单元格的属性后应用了几种启发式方法:

  1. 如果一个单元格的center.y等于该节的最后一项的center.y,则该单元格位于该节的最后一行。
  2. 如果CGRectGetMaxY(frame)等于CGRectGetMaxY(self.collectionView.bounds),则该单元格位于集合视图的右边缘。

然后,我将这些计算结果存储在UICollectionViewLayoutAttributes的子类中,并编写了一个UICollectionViewCell子类,其-applyLayoutAttributes:方法基于附加属性调整其背景视图所绘制的边框。

我把整个混乱的代码放到了一个相当庞大的要点中,这样您就可以看到我做了什么。祝编码愉快。


3
我最好的解决方案是告诉每个单元格它是否在部分的最后一行或行中的最后一个单元格; 然后单元格将关闭冒犯的边框, 部分标题将绘制顶部边框以及底部, 一切都会很好。 我不知道如何做到这一点。 您描述的基本上是我在类似情况下所做的。 我向单元格添加了边框属性:
typedef NS_OPTIONS(NSInteger, TLGridBorder) {
    TLGridBorderNone = 0,
    TLGridBorderTop = 1 << 0,
    TLGridBorderRight = 1 << 1,
    TLGridBorderBottom = 1 << 2,
    TLGridBorderLeft = 1 << 3,
    TLGridBorderAll = TLGridBorderTop | TLGridBorderRight | TLGridBorderBottom | TLGridBorderLeft,
};

@interface TLGridCellView : UIView
@property (nonatomic) TLGridBorder border;
@end

然后我在我的视图控制器的单元格配置中设置了边框:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    TLGridCellView *cell = ...;

    if (indexPath.item == self collectionView:collectionView numberOfItemsInSection:indexPath.section - 1) {
        cell.border = TLGridBorderLeft;
    } else {
        cell.border = TLGridBorderLeft | TLGridBorderRight;
    }

    return cell;
}

我最终做了类似于这样的事情 - 我会尽快将其放入gist中,以便分享答案。 - Becca Royal-Gordon

3

enter image description here

我用一种简单的方法解决了这个问题。我没有给单元格添加边框,而是在单元格中添加了一个带有边框的标签。对于第一列,标签的框架与单元格相同。对于其他标签,我将x坐标设置为-0.5,使它们的边框重叠。希望能有所帮助。
以下是代码:
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];

    // Then use it
    UILabel *label = nil;
    if (cell.contentView.subviews.count > 0) {
        label = cell.contentView.subviews[0];
    } else {
        label = [[UILabel alloc] init];
    }
    label.text = @"北京";

    [label setTextAlignment:NSTextAlignmentCenter];
    [label setFont:[UIFont systemFontOfSize:14]];
    [label setCenter:cell.contentView.center];


    CGRect frame = label.frame;
    if (indexPath.row%4 == 0) {
        frame.origin.x = 0;
    } else {
        frame.origin.x = -0.5;
    }

    frame.origin.y = 0;
    frame.size.width = self.collectionView.frame.size.width / 4;
    frame.size.height = self.collectionView.frame.size.height / 9;

    [label setFrame:frame];

    if (cell.contentView.subviews.count == 0) {
        [[cell contentView] addSubview:label];
    }

    label.layer.borderWidth = 0.5;
    label.layer.borderColor = [[UIColor lightGrayColor] CGColor];


    cell.backgroundColor = [UIColor whiteColor];

    return cell;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接