UICollectionView - Горизонтальная прокрутка, горизонтальная компоновка?
У меня есть UIScrollView, который выдает сетку значков. Если бы вы представили макет для iOS Springboard, вы бы приблизились к правилу. Он имеет горизонтальный прокручиваемый свиток (точно так же, как и Springboard). Однако, похоже, что макет не совсем прав. Похоже, что он кладет предметы сверху вниз. В результате мой последний столбец содержит только две строки из-за количества отображаемых элементов. Я бы предпочел, чтобы моя последняя строка на последней странице имела 2 элемента, например, вы видели бы в Springboard.
Как это можно сделать с помощью UICollectionView и связанных с ним классов? Должен ли я писать пользовательский UICollectionViewFlowLayout?
Ответы
Ответ 1
1-й подход
Как насчет использования UIPageViewController
с массивом UICollectionViewControllers
? Вам нужно будет забрать правильное количество элементов в каждом UICollectionViewController
, но это не должно быть сложно. Вы получите точно такой же вид, как у Springboard.
Второй подход
Я подумал об этом и, на мой взгляд, вам нужно установить:
self.collectionView.pagingEnabled = YES;
и создайте собственный макет вида коллекций путем подкласса UICollectionViewLayout
. Из пользовательского объекта макета вы можете получить доступ к self.collectionView
, чтобы узнать, каков размер представления коллекции frame
, numberOfSections
и numberOfItemsInSection:
. С помощью этой информации вы можете вычислить ячейки frames
(в prepareLayout
) и collectionViewContentSize
. Вот несколько статей о создании пользовательских макетов:
Третий подход
Вы можете сделать это (или приблизиться к нему) без создания пользовательского макета. Добавьте UIScrollView
в пустой вид, включите в него пейджинг. В представлении прокрутки добавьте представление коллекции. Затем добавьте к нему ограничение ширины, проверьте код, сколько у вас элементов, и установите его constant
на правильное значение, например. (self.view.frame.size.width * numOfScreens)
. Вот как это выглядит (цифры на ячейках показывают indexPath.row
): https://www.dropbox.com/s/ss4jdbvr511azxz/collection_view.mov Если вас не устраивает способ упорядочивания ячеек, то я боюсь, вам придется пойти с 1. или 2.
Ответ 2
Вы пытались настроить направление прокрутки вашего UICollectionViewFlowLayout на горизонтальное?
[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
И если вы хотите, чтобы страница была такой же, как в плагине, вам нужно включить пейджинг в виде коллекции так:
[yourCollectionView setPagingEnabled:YES];
Ответ 3
Вам нужно уменьшить высоту UICollectionView
до высоты своей ячейки/позиции и выбрать "Horizontal
" из "Scroll Direction
", как показано на скриншоте ниже. Затем он будет прокручиваться горизонтально в зависимости от numberOfItems
, который вы вернули в своей реализации источника данных.
![enter image description here]()
Ответ 4
Просто для удовольствия, другой подход состоял бы в том, чтобы просто оставить набор подкачки и горизонтальную прокрутку, добавить метод, который изменяет порядок элементов массива для преобразования от "сверху вниз", "слева направо" на визуально 'слева направо, сверху вниз' и заполните промежуточные ячейки пустыми скрытыми ячейками, чтобы сделать интервал правильным. В случае 7 пунктов в сетке из 9 это будет выглядеть следующим образом:
[1][4][7]
[2][5][ ]
[3][6][ ]
должен стать
[1][2][3]
[4][5][6]
[7][ ][ ]
так что 1 = 1, 2 = 4, 3 = 7 и т.д., а 6 = пусто. Вы можете переупорядочить их, вычислив общее количество строк и столбцов, затем вычислить номер строки и столбца для каждой ячейки, изменить строку для столбца и наоборот, а затем у вас есть новые индексы. Когда ячейка не имеет значения, соответствующего изображению, вы можете вернуть пустую ячейку и установить для нее cell.hidden = YES;
.
Он отлично работает в приложении для звуковой платы, которое я построил, поэтому, если кто-нибудь захочет работать с кодом, я его добавлю. Для работы этого трюка требуется только небольшой код, он звучит сложнее, чем он есть!
Обновление
Я сомневаюсь, что это лучшее решение, но по запросу здесь работает код:
- (void)viewDidLoad {
// Fill an `NSArray` with items in normal order
items = [NSMutableArray arrayWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 1", @"label", @"Some value 1", @"value", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 2", @"label", @"Some value 2", @"value", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 3", @"label", @"Some value 3", @"value", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 4", @"label", @"Some value 4", @"value", nil],
[NSDictionary dictionaryWithObjectsAndKeys:@"Some label 5", @"label", @"Some value 5", @"value", nil],
nil
];
// Calculate number of rows and columns based on width and height of the `UICollectionView` and individual cells (you might have to add margins to the equation based on your setup!)
CGFloat w = myCollectionView.frame.size.width;
CGFloat h = myCollectionView.frame.size.height;
rows = floor(h / cellHeight);
columns = floor(w / cellWidth);
}
// Calculate number of sections
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return ceil((float)items.count / (float)(rows * columns));
}
// Every section has to have every cell filled, as we need to add empty cells as well to correct the spacing
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return rows*columns;
}
// And now the most important one
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView [email protected]"myIdentifier" forIndexPath:indexPath];
// Convert rows and columns
int row = indexPath.row % rows;
int col = floor(indexPath.row / rows);
// Calculate the new index in the `NSArray`
int newIndex = ((int)indexPath.section * rows * columns) + col + row * columns;
// If the newIndex is within the range of the items array we show the cell, if not we hide it
if(newIndex < items.count) {
NSDictionary *item = [items objectAtIndex:newIndex];
cell.label.text = [item objectForKey:@"label"];
cell.hidden = NO;
} else {
cell.hidden = YES;
}
return cell;
}
Если вы хотите использовать метод didSelectItemAtIndexPath
, вы должны использовать то же преобразование, которое используется в cellForItemAtIndexPath
, чтобы получить соответствующий элемент. Если у вас есть поля ячейки, вам нужно добавить их в расчёт строк и столбцов, так как они должны быть правильными, чтобы это работало.
Ответ 5
Я работаю над Xcode 6.2 и для горизонтальной прокрутки. Я изменил направление прокрутки в инспекторе атрибутов.
нажмите на collectionView- > attribute inspector- > scroll Direction- > изменить на горизонтальный
Надеюсь, это поможет кому-то.
Ответ 6
Если вы определяете UICollectionViewFlowLayout
в коде, он будет переопределять конфигурации интерфейса Builder. Следовательно, вам нужно снова определить scrollDirection
.
let layout = UICollectionViewFlowLayout()
...
layout.scrollDirection = .Horizontal
self.awesomeCollectionView.collectionViewLayout = layout
Ответ 7
Из @Erik Hunter, я отправляю полный код для создания горизонтального UICollectionView
UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[collectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
self.myCollectionView.collectionViewLayout = collectionViewFlowLayout;
В Swift
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .Horizontal
self.myCollectionView.collectionViewLayout = layout
В Swift 3.0
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .Horizontal
self.myCollectionView.collectionViewLayout = layout
Надеемся на эту помощь
Ответ 8
Мы можем выполнять одно и то же поведение Springboard с использованием UICollectionView, и для этого нам нужно написать код для пользовательского макета.
Я достиг этого с помощью моей специальной реализации класса макета с "SMCollectionViewFillLayout"
Репозиторий кода:
https://github.com/smindia1988/SMCollectionViewFillLayout
Вывод, как показано ниже:
1.png
![First.png]()
2_Code_H-Scroll_V-Fill.png
![введите описание изображения здесь]()
3_Output_H-Scroll_V-Fill.png
![введите описание изображения здесь]()
4_Code_H-Scroll_H-Fill.png
![введите описание изображения здесь]()
5_Output_H-Scroll_H-Fill.png
![введите описание изображения здесь]()
Ответ 9
Этот код хорошо работает в Swift 3.1 и Xcode 8.3.2
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
self.collectionView.collectionViewLayout = layout
self.collectionView!.contentInset = UIEdgeInsets(top: -10, left: 0, bottom:0, right: 0)
if let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.itemSize = CGSize(width: self.view.frame.size.width-40, height: self.collectionView.frame.size.height-10)
layout.invalidateLayout()
}
}
Ответ 10
для xcode 8 я сделал это, и он работал:
![]()
Ответ 11
Вы можете написать собственный макет UICollectionView
, чтобы достичь этого, вот демонстрационный образ моей реализации:
![demo image demo image]()
Здесь репозиторий кода: KSTCollectionViewPageHorizontalLayout
@iPhoneDev (возможно, это тоже поможет)