具有动态高度的UICollectionView错误 [英] A UICollectionView bug with a dynamic height
问题描述
由于我已经在这个问题上苦苦挣扎了3天并且已经两次问过它,但可能还不清楚,我已经决定调查这个问题&用这个视图发现了一个错误行为。
Since I have been struggling for 3 days with this problem and have asked about it twice already, but maybe was not clear, I had decided to investigate the issue & found a buggy behavior with this view.
我将展示整个简单代码,所以任何人都可以重现这个错误(iPad Air)。
I will show the entire simple code, so anyone can reproduce the bug (iPad Air).
我正在设置一个 collectionView
flowlayout,它将布局子类化以获得单元格之间的恒定间距,这是开始:
I am setting a collectionView
flowlayout that subclasses the layout to get a constant spacing between cells, and here is the start:
TopAlignedCollectionViewFlowLayout *layout = [[TopAlignedCollectionViewFlowLayout alloc] init];
CGRect size = CGRectMake(0, 0, 900, 1200);
self.GridView = [[UICollectionView alloc] initWithFrame:size
collectionViewLayout:layout];
[self.GridView registerClass:[GridCell class] forCellWithReuseIdentifier:@"Cell"];
[self.GridView setDelegate:self];
[self.GridView setDataSource:self];
[self.view addSubview:self.GridView];
然后设置我的代表就是这样简单:(高度是动态的 )
Then setting my delegates is as simple as that : (height is dynamic )
#pragma grid- main functions
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 80;
}
//cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
{
//a random dynamic height of a cell
int a = arc4random()%300;
CGSize size = CGSizeMake( 340, 240+a );
return size;
}
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier=@"Cell";
GridCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier
forIndexPath:indexPath];
cell.textL.text=[NSString stringWithFormat:@"%d",indexPath.row];
NSLog(@"%d",indexPath.row);
return cell;
}
现在是子类,以获得恒定的间距:( TopAlignedCollectionViewFlowLayout
)
Now the subclass, to get a constant spacing : (TopAlignedCollectionViewFlowLayout
)
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) {
if (nil == attributes.representedElementKind) {
NSIndexPath* indexPath = attributes.indexPath;
attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame;
}
}
return attributesToReturn;
}
#define numColumns 2
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
if (indexPath.item < numColumns) {
CGRect f = currentItemAttributes.frame;
f.origin.y = 0;
currentItemAttributes.frame = f;
return currentItemAttributes;
}
NSIndexPath* ipPrev = [NSIndexPath indexPathForItem:indexPath.item-numColumns
inSection:indexPath.section];
CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
CGFloat YPointNew = fPrev.origin.y + fPrev.size.height + 10;
CGRect f = currentItemAttributes.frame;
f.origin.y = YPointNew;
currentItemAttributes.frame = f;
return currentItemAttributes;
}
任何人都可以检查并看到滚动一段时间后,你得到一个最近由他们的单元格填充的空格的奇怪效果,如:
Anyone can check and see that after you scroll for a while, you get a strange effect of blank spaces that are filled lately by their cells,something like :
1 2
3 4
6
8
注意:5-7稍后会加载。
EDIT1:
从单元格大小委托方法中删除随机高度,将其设置为恒定高度,解决了这个问题。
问题是:单元格的高度必须是动态的。
Removing the random height from the cell size delegate method, set it to be constant height, solves this issue.
Problem is: Cell's height must be dynamic.
EDIT2:
将随机高度(int a)设置得更小,也使问题消失,(< 100),意味着越小单元格之间的距离高度,更有可能不会出现问题。
Setting the random height (int a) to be smaller, makes also the problem to disappear,(<100), means that the smaller the distance height between cells, more likely the problem will not occur .
EDIT3!
我设法在单元格之间设置一个恒定的距离,而不是布局的子类,而是我自己的内存b y保存前一个单元格原点和高度,所以我有恒定的间距,但问题又回来了!似乎如果单元格处于某种特定结构中,它会使回调方法创建单元格,而不是及时调用!哇,我真的很想知道以前没有人见过这个..
这里是我的实现来创建没有子类化的间距,这也导致了问题:
I have managed to set a constant distance between cells, not with subclass of the layout, but with my own memory by saving the previous cell origin and height, so i have got the constant spacing but the problem is back again ! seems that if the cells are in some certain structure, it makes the callback method that create cells, to not being called in time ! wow , i am really wondering how no one had seen this before .. here is my implementation to create spacing with no subclassing,that also cause the problem:
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier=@"Cell";
GridCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.textL.text=[NSString stringWithFormat:@"%ld",(long)indexPath.row];
NSLog(@"%d",indexPath.row);
if(indexPath.row>1)
{
NSIndexPath* ipPrev = [NSIndexPath indexPathForItem:indexPath.item-2 inSection:indexPath.section];
float prey=[[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"y:%ld",(long)ipPrev.row]] floatValue];
float preh=[[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"h:%ld",(long)ipPrev.row]] floatValue];
cell.frame=CGRectMake(cell.frame.origin.x, preh+prey+10, cell.frame.size.width, cell.frame.size.height);
[[NSUserDefaults standardUserDefaults] setFloat:cell.frame.origin.y forKey:[NSString stringWithFormat:@"y:%ld",(long)indexPath.row]];
[[NSUserDefaults standardUserDefaults] setFloat:cell.frame.size.height forKey:[NSString stringWithFormat:@"h:%ld",(long)indexPath.row]];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(@"this index:%d",indexPath.row);
NSLog(@"this cell y:%f",cell.frame.origin.y);
NSLog(@"this cell height:%f",cell.frame.size.height);
NSLog(@"previous index:%ld",(long)ipPrev.row);
NSLog(@"previous cell y: %@",[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"y:%ld",(long)ipPrev.row]]);
NSLog(@"previous cell height: %@",[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"h:%ld",(long)ipPrev.row]]);
NSLog(@"------------------------");
}
return cell;
}
推荐答案
似乎是当图像大于屏幕尺寸时,UICollectionView中的一个严重错误。
Seems its a serious bug in UICollectionView, when images are bigger than screen size.
1。 UICollectionView回退到UIScrollView
2. 大型UICollectionViewCell随着自定义布局而消失
3. http://stripysock.com.au/blog/2013/3/14/working-around-a-bug-in-uicollectionview
这么多的工作和时间,对于苹果这个愚蠢的错误,可重复使用的细胞只会引起许多奇怪行为的头痛。
So much work and time, for this stupid bug of apple with the reusable cells that causes nothing but headache with so many strange behaviours.
对于没有这种行为的开发人员问题我可以说 - 只是尝试设置动态高度图像和iPad模拟器,你会看到令人难以置信的错误。
For developers who didn't have the problem i can say- just try to set dynamic height images, and iPad simulator, and you will see bugs that are just unbelievable.
所以没有答案对我来说,我必须由我自己实施整个事情使用scrollview,因为我不想再依赖于这样的事情 PSTCollectionView
So no answer for me, i will have to implement the whole thing by my self with a scrollview ,since i dont want to be depended again on things such PSTCollectionView
这篇关于具有动态高度的UICollectionView错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!