Рассмотрим a UICollectionView
с раскладкой потока и горизонтальным направлением. По умолчанию ячейки упорядочиваются сверху вниз, слева направо. Вот так:
1 4 7 10 13 16
2 5 8 11 14 17
3 6 9 12 15 18
В моем случае просмотр коллекции выгружается, и он был спроектирован таким образом, чтобы определенное количество ячеек соответствовало каждой странице. Таким образом, более естественным упорядочением было бы следующее:
1 2 3 10 11 12
4 5 6 - 13 14 15
7 8 9 16 17 18
Что было бы самым простым в достижении этого, если не реализовать собственный собственный макет? В частности, я не хочу потерять любую функциональность, которая предоставляется бесплатно с помощью UICollectionViewFlowLayout
(например, вставки/удаление анимаций).
Или вообще, как вы реализуете функцию переупорядочения f(n)
в макете потока? То же самое может быть применимо, например, к упорядочению справа налево.
Мой подход до сих пор
Мой первый подход заключался в подклассе UICollectionViewFlowLayout
и переопределении layoutAttributesForItemAtIndexPath:
:
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *reorderedIndexPath = [self reorderedIndexPathOfIndexPath:indexPath];
UICollectionViewLayoutAttributes *layout = [super layoutAttributesForItemAtIndexPath:reorderedIndexPath];
layout.indexPath = indexPath;
return layout;
}
Где reorderedIndexPathOfIndexPath:
- f(n)
. Вызывая super
, мне не нужно вычислять компоновку каждого элемента вручную.
Кроме того, мне пришлось переопределить layoutAttributesForElementsInRect:
, который является методом, который используется макетом для выбора отображаемых элементов.
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *result = [NSMutableArray array];
NSInteger sectionCount = 1;
if ([self.collectionView.dataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)])
{
sectionCount = [self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView];
}
for (int s = 0; s < sectionCount; s++)
{
NSInteger itemCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:s];
for (int i = 0; i < itemCount; i++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:s];
UICollectionViewLayoutAttributes *layout = [self layoutAttributesForItemAtIndexPath:indexPath];
if (CGRectIntersectsRect(rect, layout.frame))
{
[result addObject:layout];
}
}
}
return result;
}
Здесь я просто пробую каждый элемент, и если он находится в заданном rect
, я возвращаю его.
Если этот подход является способом, у меня есть следующие более конкретные вопросы:
- Можно ли упростить переопределение
layoutAttributesForElementsInRect:
или сделать его более эффективным? - Я что-то упустил? По крайней мере, замена ячеек разных страниц приводит к нечетным результатам. Я подозреваю, что это связано с
initialLayoutAttributesForAppearingItemAtIndexPath:
иfinalLayoutAttributesForDisappearingItemAtIndexPath:
, но я не могу точно определить, в чем проблема. - В моем случае
f(n)
зависит от количества столбцов и строк каждой страницы. Есть ли способ извлечь эту информацию изUICollectionViewFlowLayout
, за исключением жесткого кодирования? Я думал о запросеlayoutAttributesForElementsInRect:
с границами представления коллекции и выводил строки и столбцы оттуда, но это также неэффективно.