4

我正在使用 UICollectionView 来布置一堆按标题的第一个字母划分的单元格。每个单元格周围都应该有一个非常细的边框,并且节标题应该在上面和下面都有边框。这是我目前的原型:

由大小相同的大单元格组成的网格,四个一排,各部分之间带有细长的浅灰色标题。 窄灰色边框显示单元格和分隔符的边缘。

我通过以下规则实现当前外观:

  1. 描边每个单元格的右边缘和下边缘。
  2. 描边每个部分标题的底部边缘。

这和我想要的非常接近,但是有两个缺陷:

  1. 如果部分标题之前的行未满,则标题顶部的边框会在屏幕右边缘附近停止。
  2. 在此屏幕截图中不可见,但如果一行已满,则该行中最后一个单元格的右边框仍被绘制,这在屏幕边缘看起来有点奇怪。

解决此问题的最佳方法是以某种方式告诉每个单元格是在一个部分的最后一行还是在一行中的最后一个单元格;然后单元格将关闭有问题的边框,部分标题将绘制顶部边框和底部边框,并且一切都将是笨拙的。不过,我不知道如何实现这一目标。

关于如何管理它的任何想法,或者其他方式来获得我想要的外观?我目前正在使用 UICollectionViewFlowLayout。

4

3 回答 3

4

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

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

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

我已经把整个混乱变成了一个相当大的要点,所以你可以确切地看到我做了什么。快乐的黑客。

于 2013-07-14T03:34:58.123 回答
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;
}
于 2013-07-12T15:27:45.870 回答
3

在此处输入图像描述

我以一种简单的方式解决了这个问题。我没有在单元格中添加边界,而是在单元格中添加了一个带有边界的标签。对于第一列,标签的框架与单元格相同。对于另一个标签,我将 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;
}
于 2015-09-04T11:56:03.247 回答