Ein UICollectionView-Fehler mit einer dynamischen Höhe
Da ich seit 3 Tagen mit diesem Problem kämpfe und bereits zweimal danach gefragt habe, aber vielleicht nicht klar war, hatte ich beschlossen, das Problem zu untersuchen und ein fehlerhaftes Verhalten mit dieser Ansicht zu finden.
Ich werde den gesamten einfachen Code anzeigen, damit jeder den Fehler reproduzieren kann (iPad Air).
Ich setze eincollectionView
Flowlayout, das das Layout in Unterklassen unterteilt, um einen konstanten Abstand zwischen den Zellen zu erhalten. Hier ist der Anfang:
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];
Dann ist das Einstellen meiner Stellvertreter so einfach: (Höhe ist dynamisch )
#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;
}
Nun die Unterklasse, um einen konstanten Abstand zu erhalten: (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;
}
Jeder kann überprüfen und sehen, dass Sie nach einem Bildlauf einen seltsamen Effekt von Leerzeichen erhalten, die in letzter Zeit von ihren Zellen ausgefüllt wurden.
1 2
3 4
6
8
HINWEIS: 5-7 werden später geladen.
EDIT1:
Durch Entfernen der zufälligen Höhe aus der Delegatmethode für die Zellengröße und Festlegen einer konstanten Höhe wird dieses Problem behoben.
Das Problem ist: Die Höhe der Zelle muss dynamisch sein.
EDIT2: Wird die zufällige Höhe (int a) kleiner eingestellt, verschwindet auch das Problem (<100). Je kleiner der Abstand zwischen den Zellen ist, desto wahrscheinlicher tritt das Problem nicht auf.
EDIT3!
Ich habe es geschafft, einen konstanten Abstand zwischen den Zellen einzustellen, nicht mit der Unterklasse des Layouts, sondern mit meinem eigenen Gedächtnis, indem ich den vorherigen Ursprung und die Höhe der Zellen gespeichert habe.Ich habe also den konstanten Abstand, aber das Problem ist wieder da ! Wenn sich die Zellen in einer bestimmten Struktur befinden, führt dies anscheinend dazu, dass die Rückrufmethode, mit der Zellen erstellt werden, nicht rechtzeitig aufgerufen wird. Wow, ich frage mich wirklich, wie niemand dies zuvor gesehen hat. Hier ist meine Implementierung zum Erstellen von Abständen ohne Unterklassen, die ebenfalls das Problem verursachen:
-(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;
}