iOS - Создание экрана SpringBoard
Я пытаюсь так создать представление коллекции, которое ведет себя как экран трамплина iOS. Это означает, что я хочу иметь коллекционное представление со всеми моими элементами и иметь контроллер страницы под сеткой (как экран трамплина). Я также хочу реализовать тот же режим редактирования. Это означает, что мои значки находятся в режиме редактирования, и я могу перетаскивать их с одной страницы на другую таким образом, чтобы страница не была заполненной. Я пытался настроить горизонтальный просмотр одной коллекции, но он работает не так, как я хочу. Прежде всего, значки добавляются одна под другой, а не одна рядом с другой. во-вторых, у меня нет точек страницы таким образом, и пользователь не может размещать значки на разных страницах. Я также попытался установить контроллер страницы и поместить на каждую страницу представление коллекции. В этом случае я получаю, что в режиме редактирования я не могу переходить между экранами. Я предполагаю, что это потому, что у меня есть более одного представления коллекции, и они не взаимодействуют друг с другом. Хотя я и по-другому использую представление прокрутки и пытаюсь поместить представление коллекции в это представление прокрутки. Но для меня это звучит как не очень элегантное решение.
У кого-нибудь есть идеи о том, как создать такую сцену?
Изменить: я думаю, что ответ на мою проблему скрывается в этом вопросе. Он описывает ту же ситуацию, которую я хочу иметь: представление коллекции, которое прокручивается горизонтально, с разбивкой по страницам, и что порядок значков перемещается не вертикально, а горизонтально. Там есть частично хороший ответ. Я говорю, что это частично хорошо, так как ответ описывает подкласс UICollectionViewFlowLayout, но в загруженном примере проекта подкласс имеет UICollectionViewLayout, и я думаю, что весь смысл состоял в том, чтобы поддерживать функции, которые имеет UICollectionViewFlowLayout. Этот вопрос был задан год назад, поэтому я считаю, что у кого-то есть ответ, или, по крайней мере, я надеюсь.
1 ответ
У меня есть частичное решение моего вопроса. Я использовал ответ (Богдана) на связанный вопрос выше. Вот код:
layout.h:
#import <UIKit/UIKit.h>
@interface V9Layout : UICollectionViewLayout
@property (nonatomic, assign) NSInteger itemsInOneRow;
@property (nonatomic, assign) NSInteger itemsInOneCol;
@property (nonatomic, assign) CGSize itemSize;
@end
layout.m:
#import "V9Layout.h"
@interface V9Layout()
-(void)calculateLayoutProperties;
-(int)pagesInSection:(NSInteger)section;
@property (nonatomic, strong) NSMutableArray *frames;
@property (nonatomic, assign) CGFloat lineSpacing;
@property (nonatomic, assign) CGFloat interitemSpacing;
@property (nonatomic, assign) CGSize pageSize;
@end
@implementation V9Layout
@synthesize itemsInOneRow = _itemsInOneRow, itemsInOneCol = _itemsInOneCol, itemSize = _itemSize;
@synthesize lineSpacing = _lineSpacing, interitemSpacing = _interitemSpacing;
@synthesize frames = _frames;
- (id)init
{
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (void)setup
{
self.itemsInOneRow = 3;
self.itemsInOneCol = 4;
self.frames = [NSMutableArray array];
}
-(void)calculateLayoutProperties {
self.pageSize = self.collectionView.bounds.size;
// The width of all line spacings is equal to width of ONE item. The same for interitem spacing
CGFloat itemWidth = self.pageSize.width / (self.itemsInOneRow + 1); // +1 because we all spaces make width of one additional item
CGFloat itemHeight = self.pageSize.height / (self.itemsInOneCol + 1); // the same
NSLog(@"calculateLayoutProperties item width: %f, item height: %f", itemWidth, itemHeight);
self.itemSize = CGSizeMake(itemWidth, itemHeight);
// this part is only to make a global parameter, because I'm using this data to create the size of the UICollectionViewCell. I think I need to use a delegate method for the UICollectionViewCell to ask the UICollectionViewLayout for the calculated size of cell.
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
if (standardUserDefaults) {
[standardUserDefaults setObject:[NSNumber numberWithFloat:itemWidth] forKey:@"cellWidth"];
[standardUserDefaults setObject:[NSNumber numberWithFloat:itemHeight] forKey:@"cellHeight"];
[standardUserDefaults synchronize];
}
// spacing for x
self.lineSpacing = (self.pageSize.width - (self.itemsInOneRow * self.itemSize.width)) / (self.itemsInOneRow + 1);
// spacing for y
self.interitemSpacing = (self.pageSize.height - (self.itemsInOneCol * self.itemSize.height)) / (self.itemsInOneCol + 1);
}
-(int)pagesInSection:(NSInteger)section {
NSLog(@"v9layout: numberOfItemsInSection is %ld", (long)[self.collectionView numberOfItemsInSection:section]);
return ([self.collectionView numberOfItemsInSection:section] - 1) / (self.itemsInOneRow * self.itemsInOneCol) + 1;
}
-(CGSize)collectionViewContentSize {
// contentSize.width is equal to pages * pageSize.width
NSInteger sections = 1;
if ([self.collectionView respondsToSelector:@selector(numberOfSections)]) {
sections = [self.collectionView numberOfSections];
}
int pages = 0;
for (int section = 0; section < sections; section++) {
pages = pages + [self pagesInSection:section];
}
return CGSizeMake(pages * self.pageSize.width, self.pageSize.height);
}
-(void)prepareLayout {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self calculateLayoutProperties];
});
[self.frames removeAllObjects];
NSInteger sections = 1;
if ([self.collectionView respondsToSelector:@selector(numberOfSections)]) {
sections = [self.collectionView numberOfSections];
}
int pagesOffset = 0; // Pages that are used by prevoius sections
int itemsInPage = self.itemsInOneRow * self.itemsInOneCol;
for (int section = 0; section < sections; section++) {
NSMutableArray *framesInSection = [NSMutableArray array];
int pagesInSection = [self pagesInSection:section];
int itemsInSection = [self.collectionView numberOfItemsInSection:section];
for (int page = 0; page < pagesInSection; page++) {
int itemsToAddToArray = itemsInSection - framesInSection.count;
int itemsInCurrentPage = itemsInPage;
if (itemsToAddToArray < itemsInPage) { // If there are less cells than expected (typically last page of section), we go only through existing cells.
itemsInCurrentPage = itemsToAddToArray;
}
for (int itemInPage = 0; itemInPage < itemsInCurrentPage; itemInPage++) {
CGFloat originX = (pagesOffset + page) * self.pageSize.width + self.lineSpacing + (itemInPage % self.itemsInOneRow) * (self.itemSize.width + self.lineSpacing);
CGFloat originY = self.interitemSpacing + (itemInPage / self.itemsInOneRow) * (self.itemSize.height + self.interitemSpacing);
CGRect itemFrame = CGRectMake(originX, originY, self.itemSize.width, self.itemSize.height);
[framesInSection addObject:NSStringFromCGRect(itemFrame)];
}
}
[self.frames addObject:framesInSection];
pagesOffset += pagesInSection;
}
}
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *attributes = [NSMutableArray array];
NSInteger sections = 1;
if ([self.collectionView respondsToSelector:@selector(numberOfSections)]) {
sections = [self.collectionView numberOfSections];
}
int pagesOffset = 0;
int itemsInPage = self.itemsInOneRow * self.itemsInOneCol;
for (int section = 0; section < sections; section++) {
int pagesInSection = [self pagesInSection:section];
int itemsInSection = [self.collectionView numberOfItemsInSection:section];
for (int page = 0; page < pagesInSection; page++) {
CGRect pageFrame = CGRectMake((pagesOffset + page) * self.pageSize.width, 0, self.pageSize.width, self.pageSize.height);
if (CGRectIntersectsRect(rect, pageFrame)) {
int startItemIndex = page * itemsInPage;
int itemsInCurrentPage = itemsInPage;
if (itemsInSection - startItemIndex < itemsInPage) {
itemsInCurrentPage = itemsInSection - startItemIndex;
}
for (int itemInPage = 0; itemInPage < itemsInCurrentPage; itemInPage++) {
UICollectionViewLayoutAttributes *itemAttributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:startItemIndex + itemInPage inSection:section]];
if (CGRectIntersectsRect(itemAttributes.frame, rect)) {
[attributes addObject:itemAttributes];
}
}
}
}
pagesOffset += pagesInSection;
}
return attributes;
}
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attributes.frame = CGRectFromString(self.frames[indexPath.section][indexPath.item]);
return attributes;
}
@end
Это реализует горизонтальный пейджинг с порядком ячеек, расположенных один рядом друг с другом, а не один под другим. Я все еще хочу добавить возможность перетаскивания, чтобы пользователь мог изменять порядок ячеек. Я задаю этот вопрос об этом. Надеюсь, я найду ответ и обновлю этот ответ.