2016-04-27 2 views
3

У меня есть набор данных, который разделен на несколько разделов, однако я хотел бы отображать это в коллекцииView без перерывов между разделами. Вот пример того, что я хочу добиться:UICollectionView удаляет разрывы разделов с помощью UICollectionViewFlowLayout

Instead of: 
0-0 0-1 0-2 
0-3 
1-0 1-1 
2-0 
3-0 

I want: 
0-0 0-1 0-2 
0-3 1-0 1-1 
2-0 3-0 

Я понимаю, что решение, вероятно, лежит с пользовательским UICollectionViewLayout подклассе, но я не знаю, как добиться чего-то подобного.

Благодаря

+0

Использование только одного раздела даст желаемый результат. Есть ли причина, по которой вам нужно использовать несколько разделов? – bsmith11

+0

Я использую NSFetchedResultsController, который имеет определенный разделNameKeyPath, который разбивает полученные результаты на эти разделы. Этот контроллер и кэшированные результаты распределяются между этим набором CollectionView и другим табличным представлением, которое отображает разрывы раздела - следовательно, необходимо установить sectionNameKeyPath. Я понимаю, что могу сделать какое-то смешное переключение NSIndexPath, чтобы он работал в одном разделе для коллекцииView, но я считаю, что самым чистым решением является настройка макета потока. –

+0

Я не верю, что существует чистый способ добиться того, чего вы хотите, без подкласса 'UICollectionViewLayout'. Что делать, если вы использовали два отдельных 'NSFetchedResultsController'? – bsmith11

ответ

0

Вы правы, что вам нужно подкласс UICollectionViewLayout. Суть, которую нужно понять перед запуском, заключается в том, что вам нужно рассчитать по крайней мере позицию и размер для каждой ячейки в виде коллекции. UICollectionViewLayout - это всего лишь структурированный способ предоставления этой информации. Вы получаете структуру, но вам нужно предоставить все остальное самостоятельно.

Есть 4 способа, которые необходимо переопределить:

  • подготовить
  • invalidateLayout
  • layoutAttributesForItemAtIndexPath
  • layoutAttributesForElementsInRect

Один Хитрость заключается в том, чтобы кэшировать расположение атрибутов в таблице поиска (словарь):

var cachedItemAttributes = [IndexPath: UICollectionViewLayoutAttributes]() 

В подготовить, рассчитать расположение атрибутов для каждого indexPath в вашем CollectionView:

override func prepare() { 
    super.prepare() 
    calculateAttributes() 
} 

В invalidateLayout сброса кэшированные атрибуты макета и пересчитать их:

override func invalidateLayout() { 
    super.invalidateLayout() 
    cachedItemAttributes = [:] 
    calculateAttributes() 
} 

В layoutAttributesForItemAtIndexPath вы используете поиск стол, чтобы вернуть правильный макет атрибуты:

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 
    return cachedItemAttributes[indexPath] 
} 

В layoutAttributesForElementsInRect вы отфильтровать таблицу поиска для элементов в пределах указанного прямоугольника:

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
    return cachedItemAttributes.filter { rect.intersects($0.value.frame) }.map { $0.value } 
} 

Заключительная часть головоломки является фактическим расчетом атрибуты макета. Здесь я приведу только псевдо-код:

func calculateAttributes() { 
    // For each indexpath (you can get this from the collectionView property using numberOfSections and numberOfItems:inSection) 
    // calculate the frame, i.e the origin point and size of each cell in your collectionView and set it with UICollectionViewLayoutAttributes.frame 
    // There are many other properties on UICollectionViewLayoutAttributes that you can tweak for your layout, but frame is a good starting point from which you can start experimenting. 
    // Add the layout attributes to the lookup table 
    // end loop 
} 

Чтобы ответить на ваш вопрос, вот псевдо-код, чтобы вычислить положение каждой ячейки:

// If width of cell + current width of row + spacing, insets and margins exceeds the available width 
// move to next row. 
// else 
// cell origin.x = current width of row + interitem spacing 
// cell origin.y = number of rows * (row height + spacing) 
// endif 

Если вам нужен ваш собственный макет в настраиваться, то либо использовать UICollectionViewDelegateFlowLayout, если доступных сигнатур достаточно, либо определить свой собственный, который наследуется от UICollectionViewDelegateFlowLayout или UICollectionViewDelegate.Поскольку ваш протокол наследуется от UICollectionViewDelegateFlowLayout, который сам наследуется от UICollectionViewDelegate, вы можете установить его непосредственно как делегат collectionView в вашем диспетчере просмотра. В вашем макете просмотра пользовательских коллекций вам просто нужно передать делегата из UICollectionViewDelegate в свой собственный протокол, чтобы использовать его. Не забудьте обработать случаи, когда сбой кастинга или методы протокола не реализованы делегатом.

Смежные вопросы