From 0329167b5e760c73b5b9b276ad47cf1de03dfebd Mon Sep 17 00:00:00 2001 From: muer2000 Date: Wed, 5 Jun 2013 13:56:36 +0800 Subject: [PATCH] Update PSCollectionView.m MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.Add vertical margin and horizontal margin. 增加纵向和横向间距属性。 2.Remove all rows that are not inside the visible rect and redundant. 修改移除可见视图的代码,用于解决reloadData全部刷新的问题 --- PSCollectionView.m | 58 ++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/PSCollectionView.m b/PSCollectionView.m index 2e5d405..1e15a05 100644 --- a/PSCollectionView.m +++ b/PSCollectionView.m @@ -23,7 +23,7 @@ #import "PSCollectionView.h" -#define kMargin 8.0 +#define kMargin 5.0 static inline NSString * PSCollectionKeyForIndex(NSInteger index) { return [NSString stringWithFormat:@"%d", index]; @@ -152,7 +152,6 @@ - (id)initWithFrame:(CGRect)frame { self.lastOffset = 0.0; self.offsetThreshold = floorf(self.height / 4.0); - self.colWidth = 0.0; self.numCols = 0; self.numColsPortrait = 0; @@ -163,6 +162,9 @@ - (id)initWithFrame:(CGRect)frame { self.visibleViews = [NSMutableDictionary dictionary]; self.viewKeysToRemove = [NSMutableArray array]; self.indexToRectMap = [NSMutableDictionary dictionary]; + + self.verticalMargin = kMargin; + self.horizontalMargin = kMargin; } return self; } @@ -197,10 +199,8 @@ - (void)layoutSubviews { } else { // Recycles cells CGFloat diff = fabsf(self.lastOffset - self.contentOffset.y); - if (diff > self.offsetThreshold) { self.lastOffset = self.contentOffset.y; - [self removeAndAddCellsIfNecessary]; } } @@ -211,29 +211,24 @@ - (void)layoutSubviews { - (void)relayoutViews { self.numCols = UIInterfaceOrientationIsPortrait(self.orientation) ? self.numColsPortrait : self.numColsLandscape; - // Reset all state - [self.visibleViews enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - PSCollectionViewCell *view = (PSCollectionViewCell *)obj; - [self enqueueReusableView:view]; - }]; - [self.visibleViews removeAllObjects]; - [self.viewKeysToRemove removeAllObjects]; + // Reset all state [self.indexToRectMap removeAllObjects]; - + // This is where we should layout the entire grid first NSInteger numViews = [self.collectionViewDataSource numberOfRowsInCollectionView:self]; CGFloat totalHeight = 0.0; - CGFloat top = kMargin; - + CGFloat top = self.verticalMargin; + // Add headerView if it exists if (self.headerView) { top = self.headerView.top; self.headerView.width = self.width; - [self addSubview:self.headerView]; - top += self.headerView.height; + if (self.headerView.superview == nil) + [self addSubview:self.headerView]; + top = top + self.headerView.height + self.verticalMargin; } - + if (numViews > 0) { // This array determines the last height offset on a column NSMutableArray *colOffsets = [NSMutableArray arrayWithCapacity:self.numCols]; @@ -242,10 +237,10 @@ - (void)relayoutViews { } // Calculate index to rect mapping - self.colWidth = floorf((self.width - kMargin * (self.numCols + 1)) / self.numCols); + self.colWidth = floorf((self.width - self.horizontalMargin * (self.numCols + 1)) / self.numCols); + for (NSInteger i = 0; i < numViews; i++) { NSString *key = PSCollectionKeyForIndex(i); - // Find the shortest column NSInteger col = 0; CGFloat minHeight = [[colOffsets objectAtIndex:col] floatValue]; @@ -257,8 +252,8 @@ - (void)relayoutViews { minHeight = colHeight; } } - - CGFloat left = kMargin + (col * kMargin) + (col * self.colWidth); + + CGFloat left = self.horizontalMargin + (col * self.horizontalMargin) + (col * self.colWidth); CGFloat top = [[colOffsets objectAtIndex:col] floatValue]; CGFloat colHeight = [self.collectionViewDataSource collectionView:self heightForRowAtIndex:i]; @@ -268,8 +263,8 @@ - (void)relayoutViews { [self.indexToRectMap setObject:NSStringFromCGRect(viewRect) forKey:key]; // Update the last height offset for this column - CGFloat heightOffset = colHeight > 0 ? top + colHeight + kMargin : top; - + CGFloat heightOffset = colHeight > 0 ? top + colHeight + self.verticalMargin : top; + [colOffsets replaceObjectAtIndex:col withObject:[NSNumber numberWithFloat:heightOffset]]; } @@ -284,7 +279,8 @@ - (void)relayoutViews { if (self.footerView) { self.footerView.top = totalHeight; self.footerView.width = self.width; - [self addSubview:self.footerView]; + if (self.footerView.superview == nil) + [self addSubview:self.footerView]; totalHeight += self.footerView.height; } @@ -304,17 +300,16 @@ - (void)removeAndAddCellsIfNecessary { if (numViews == 0) return; - // NSLog(@"diff: %f, lastOffset: %f", diff, self.lastOffset); // Find out what rows are visible CGRect visibleRect = CGRectMake(self.contentOffset.x, self.contentOffset.y, self.width, self.height); visibleRect = CGRectInset(visibleRect, 0, -1.0 * self.offsetThreshold); - + // Remove all rows that are not inside the visible rect [self.visibleViews enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { PSCollectionViewCell *view = (PSCollectionViewCell *)obj; CGRect viewRect = view.frame; - if (!CGRectIntersectsRect(visibleRect, viewRect)) { + if (!CGRectIntersectsRect(visibleRect, viewRect) || (PSCollectionIndexForKey(key) >= numViews)) { [self enqueueReusableView:view]; [self.viewKeysToRemove addObject:key]; } @@ -322,7 +317,6 @@ - (void)removeAndAddCellsIfNecessary { [self.visibleViews removeObjectsForKeys:self.viewKeysToRemove]; [self.viewKeysToRemove removeAllObjects]; - if ([self.visibleViews count] == 0) { topIndex = 0; bottomIndex = numViews; @@ -336,24 +330,21 @@ - (void)removeAndAddCellsIfNecessary { return (NSComparisonResult)NSOrderedSame; } }]; + topIndex = [[sortedKeys objectAtIndex:0] integerValue]; bottomIndex = [[sortedKeys lastObject] integerValue]; - topIndex = MAX(0, topIndex - (bufferViewFactor * self.numCols)); bottomIndex = MIN(numViews, bottomIndex + (bufferViewFactor * self.numCols)); } - // NSLog(@"topIndex: %d, bottomIndex: %d", topIndex, bottomIndex); - // Add views for (NSInteger i = topIndex; i < bottomIndex; i++) { NSString *key = PSCollectionKeyForIndex(i); CGRect rect = CGRectFromString([self.indexToRectMap objectForKey:key]); - // If view is within visible rect and is not already shown if (![self.visibleViews objectForKey:key] && CGRectIntersectsRect(visibleRect, rect)) { // Only add views if not visible PSCollectionViewCell *newCell = [self.collectionViewDataSource collectionView:self cellForRowAtIndex:i]; - newCell.frame = CGRectFromString([self.indexToRectMap objectForKey:key]); + newCell.frame = rect; [self addSubview:newCell]; // Setup gesture recognizer @@ -367,6 +358,7 @@ - (void)removeAndAddCellsIfNecessary { [self.visibleViews setObject:newCell forKey:key]; } } + } #pragma mark - Reusing Views