Как создать UICollectionView с заголовками столбцов и строк?

Я хочу создать UICollectionView, который выглядит так:

Да. Это.

Он не будет прокручиваться или редактироваться. В настоящее время мне интересно, как написать макет для этого. Я предполагаю, что это не будет подклассом UICollectionViewFlowLayout. Я могу придумать несколько способов, но мне было любопытно, есть ли какой-нибудь «правильный» способ. Клетки будут анимированы.

Должна ли каждая строка или столбец быть отдельным разделом?


person rsmoz    schedule 29.05.2014    source источник
comment
Для меня это выглядит как пользовательский макет, но, возможно, не потоковый макет.   -  person matt    schedule 29.05.2014
comment
Если вам не нужно редактировать или прокручивать, вы также можете использовать статическую сборку uitableview с использованием раскадровки.   -  person Andrea    schedule 29.05.2014


Ответы (2)


Я сделал что-то вроде того, что вы хотите, с подклассом 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;
}
person rdelmar    schedule 29.05.2014
comment
Как быть с ярлыками? - person rsmoz; 29.05.2014
comment
@rsmoz, я создал пользовательскую ячейку с меткой по центру (как по x, так и по y) и размером 60x60 (с ячейкой 80x80). - person rdelmar; 29.05.2014
comment
Могу ли я увидеть определенные вами методы делегирования данных? - person rsmoz; 29.05.2014
comment
Я в основном хочу посмотреть, как выглядят ваши массивы. - person rsmoz; 29.05.2014
comment
Спасибо! Это полезно. - person rsmoz; 29.05.2014
comment
Вы также можете попробовать использовать пользовательский макет. Потому что он может обрабатывать горизонтальную прокрутку, если номер столбца очень большой. stackoverflow.com/a/35362818/833885 - person brianLikeApple; 12.02.2016

Вы можете сделать это с помощью UICollectionViewFlowLayout, но если вы пойдете по этому пути, вам нужно тщательно подсчитать и правильно заполнить отступы (то есть верхний левый и другие «пустые» ячейки). Если вы неправильно подсчитали, это очевидно, потому что поток быстро все разрушает, и вы найдете ячейки заголовка на полпути вниз по столбцам. (у меня было подобное)

Я сделал это только из-за боязни пользовательских макетов, но на самом деле это так же просто, как UITableView. Если ваш макет вообще не прокручивается, то ваш будет особенно простым, поскольку вашей единственной реальной работой будет вычисление значений кадров для ячеек, которые будут возвращены в layoutAttributesForItemAtIndexPath. Поскольку все ваше представление помещается в видимую область, layoutAttributesForElementsInRect будет означать, что вы просто выполняете итерацию по всем ячейкам в представлении. collectionViewContentSize будет размером вашего представления.

Глядя на свой образец изображения, вы можете найти удобным организовать свои данные в виде словаря массивов, по одному на столбец. Вы можете получить массив столбцов по имени ("A", "B" и т. д.), а позиция в массиве соответствует значению в самом левом столбце, который вы можете назвать "индекс".

Есть много других методов, которые вы можете использовать, но это основные, и они заставят ваш основной дисплей работать.

person Adam Eberbach    schedule 29.05.2014