如何创建带有列标题和行标题的 UICollectionView?

Posted

技术标签:

【中文标题】如何创建带有列标题和行标题的 UICollectionView?【英文标题】:How do I create a UICollectionView with column and row headers? 【发布时间】:2014-05-29 04:22:14 【问题描述】:

我想创建一个如下所示的 UICollectionView:

它不能滚动或编辑。我目前想知道如何为此编写布局。我猜它不会是UICollectionViewFlowLayout 的子类。我可以想到很多方法,但很好奇是否有任何“正确”的方法。单元格将具有动画效果。

每一行或每一列都应该是它自己的部分吗?

【问题讨论】:

对我来说,它看起来像是自定义布局,但可能不是流式布局。 如果您不需要编辑或滚动,您也可以使用故事板使用静态 uitableview 构建 【参考方案1】:

我已经使用 UICollectionViewFlowLayout 的子类完成了您想要的操作。看起来是这样的,

 @implementation MultpleLineLayout 
    NSInteger itemWidth;
    NSInteger itemHeight;


-(id)init 
    if (self = [super init]) 
        itemWidth = 80;
        itemHeight = 80;
    
    return self;


-(CGSize)collectionViewContentSize 
    NSInteger xSize = [self.collectionView numberOfItemsInSection:0] * (itemWidth + 2); // the 2 is for spacing between cells.
    NSInteger ySize = [self.collectionView numberOfSections] * (itemHeight + 2);
    return CGSizeMake(xSize, ySize);


- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path 
    UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];
    NSInteger xValue;
    attributes.size = CGSizeMake(itemWidth,itemHeight);
    xValue = itemWidth/2 + path.row * (itemWidth +2);
    NSInteger yValue = itemHeight + path.section * (itemHeight +2);
    attributes.center = CGPointMake(xValue, yValue);
    return attributes;



-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect 
    NSInteger minRow =  (rect.origin.x > 0)?  rect.origin.x/(itemWidth +2) : 0; // need to check because bounce gives negative values  for x.
    NSInteger maxRow = rect.size.width/(itemWidth +2) + minRow;
    NSMutableArray* attributes = [NSMutableArray array];
    for(NSInteger i=0 ; i < self.collectionView.numberOfSections; i++) 
        for (NSInteger j=minRow ; j < maxRow; j++) 
            NSIndexPath* indexPath = [NSIndexPath indexPathForItem:j inSection:i];
            [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
        
    
    return attributes;

数据被排列为一个数组数组,其中每个内部数组为一个水平行提供数据。使用我现在在那里的值,并以您的数据为例,视图看起来像这样,

这是我有视图控制器的代码,

@interface ViewController ()
@property (strong,nonatomic) UICollectionView *collectionView;
@property (strong,nonatomic) NSArray *theData;
@end

@implementation ViewController

- (void)viewDidLoad 
    self.theData = @[@[@"",@"A",@"B",@"C"],@[@"1",@"115",@"127",@"132"],@[@"2",@"",@"",@"153"],@[@"3",@"",@"199",@""]];

    MultpleLineLayout *layout = [[MultpleLineLayout alloc] init];
    self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    self.view.backgroundColor = [UIColor blackColor];
    [self.view addSubview:self.collectionView];
    [self.collectionView registerNib:[UINib nibWithNibName:@"CustomDataCell" bundle:nil] forCellWithReuseIdentifier:@"DataCell"];



- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section 
    return [self.theData[section] count];


- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView 
    return [self.theData count];


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView  cellForItemAtIndexPath:(NSIndexPath *)indexPath 
    DataCell *cell = [collectionView  dequeueReusableCellWithReuseIdentifier:@"DataCell" forIndexPath:indexPath];
    cell.label.text = self.theData[indexPath.section][indexPath.row];
    return cell;

【讨论】:

标签如何处理? @rsmoz,我创建了一个自定义单元格,该单元格的标签居中(在 x 和 y 中),大小为 60x60(单元格为 80x80)。 我可以看看你定义的数据委托方法吗? 我基本上是想看看你的数组是什么样子的。 谢谢!这很有帮助。【参考方案2】:

您可以使用UICollectionViewFlowLayout 来做到这一点,但如果您这样做,您需要仔细计算并获得正确的填充(即左上角和其他“空”单元格)。如果你算错了,那很明显,因为流程很快就会破坏一切,你会在列的中间找到标题单元格。 (我也做过类似的事情)

我只是因为害怕自定义布局才这样做 - 但实际上它就像UITableView 一样简单。如果您的布局根本不滚动,那么您的布局将特别简单,因为您唯一真正的工作将是计算单元格的帧值,并在layoutAttributesForItemAtIndexPath 中返回。由于您的整个视图适合可见区域,layoutAttributesForElementsInRect 意味着您只需遍历视图中的所有单元格。 collectionViewContentSize 将是您视图的大小。

查看您的示例图片,您可能会发现将数据组织为数组字典很方便,每列一个。您可以按名称(“A”、“B”等)获取列数组,数组中的位置对应于最左侧列中的值,您可以将其命名为“索引”。

您可以使用更多方法,但这些都是基本方法,可以让您的基本显示正常运行。

【讨论】:

以上是关于如何创建带有列标题和行标题的 UICollectionView?的主要内容,如果未能解决你的问题,请参考以下文章

在访问报告上创建列和行

SAPUI5 - 带有工厂函数的 sap.m.Table 不显示列和项目

如何使用 olap4j 读取 mdx 中的列标题和行标题

Drupal Views:如何设置列和行的标题?

Angular > 在材质表中显示列和行

如何在 Flutter 中将列和行项居中?