iOS – 创build一个SpringBoard屏幕
我想创build一个集合视图,行为像iOS的跳板屏幕。 这意味着我想拥有一个包含所有项目的集合视图,并且在网格下面有一个页面控制器(就像跳板屏幕一样)。 我也想实现相同的编辑模式,这意味着我的图标处于编辑模式,我可以将它们从一个页面拖动到另一个页面,这样页面就不必满了。 我试图设置一个单一的集合视图水平滚动,但它不按我想要的。 首先,图标被添加到另一个之下 ,而不是一个在另一个之上。 其次,我没有这样的页面点,用户不能把图标放在不同的页面上,我也尝试设置一个页面控制器,并把每个页面放在收集视图。 在这种情况下,在编辑模式下,我无法在屏幕之间切换。 我想这是因为我有更多的一个集合视图,他们不互相交互。 我虽然另一种方式,使用滚动视图,并尝试在该滚动视图中放置一个集合视图。 但是,这听起来像一个非常不优雅的解决scheme。
有没有人有关于如何创build这样一个场景的想法?
编辑:我认为我的问题的答案隐藏在这个问题 。 它描述了我想要的相同情况:一个集合视图,横向滚动,分页,并且图标的顺序不是垂直stream动,而是水平stream动。 那里有一个很好的答案。 我说这是部分好的,因为答案描述了UICollectionViewFlowLayout的子类,但是在上传的示例项目中,子类是UICollectionViewLayout的,我认为整个过程是维护UICollectionViewFlowLayout所具有的function。 这个问题是一年前问的,所以我相信有人有答案,至less我希望。
我已经部分解决了我的问题。 我确实使用了(Bogdan的) 回答上面的链接问题 。 代码如下:
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
这实现了水平寻呼单元的顺序彼此相邻而不是彼此之下。 我仍然想添加拖放function,以便用户可以更改单元格的顺序。 我提出这个问题 。 希望,我会find答案,并更新这个答案。