UICollectionView未正确显示单元格

时间:2015-07-27 21:21:27

标签: ios objective-c

我是UICollection View的新手。有些单元格没有显示,如下图所示。这是我设置它的代码,如果有人可以解释为什么有些单元格丢失会很高兴。此外,当我向上和向下滚动时,单元格中的图像会因某种原因而改变(尽管在此屏幕截图中我对所有单元格使用相同的图像)。缺少整个第二行和第四行,并且缺少中间列。目的是使每行的三行图像彼此相邻。谢谢!

   UICollectionViewFlowLayout *layout=[UICollectionViewFlowLayout new];
   self.collectionView=[[UICollectionView alloc] initWithFrame:Frame(0,225,1080, Denormalize(screenHeight) - 225) collectionViewLayout:layout];
   [self.collectionView setDataSource:self];
   [self.collectionView setDelegate:self];

   [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
   [self.collectionView setBackgroundColor:[UIColor redColor]];
   layout.minimumLineSpacing = 0;
   layout.minimumInteritemSpacing = 0;
   layout.sectionInset = UIEdgeInsetsMake(0,0,0,0);

   [self.view addSubview:_collectionView];

#pragma mark - CollectionView delegate
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
  return self.allVideos.count;
}

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
//  cell.backgroundColor=[UIColor greenColor];

  NSDictionary *video = self.allVideos[indexPath.row];

  UIImageView *thumbnail = [UIImageView new];
  thumbnail.contentMode = UIViewContentModeScaleAspectFill;
  thumbnail.frame = cell.frame;
  thumbnail.clipsToBounds = YES;
  thumbnail.image = [UIImage imageNamed:@"DefaultAvatar.png"];
//  thumbnail.image = video[@"image"];
  [cell addSubview:thumbnail];

  return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
  return CGSizeMake(self.view.frame.size.width/3, self.view.frame.size.width/3);
}

enter image description here

1 个答案:

答案 0 :(得分:3)

这里的一个主要问题是您在cellForItemAtIndexPath中添加UIImageView作为子视图。每次细胞出列时都会运行此方法,而不是每次初始化细胞时都会运行。这意味着每当其中一个单元格像集合滚动时一样呈现时,就会在单元格上的现有图像视图上添加一个新的子视图。这将很快以图形方式导致重大问题,并使用更多内存然后打算。我要做的第一件事是子类UICollectionViewCell并将你的UIImageView添加到子类。然后,您可以在该方法中设置单元格的图像,但在该特定位置添加子视图是一个非常糟糕的主意。

这是我的方法。

首先,创建一个单元子类并公开一个方法来设置图像。

// MyCollectionViewCell.h

#import <UIKit/UIKit.h>

@interface MyCollectionViewCell : UICollectionViewCell

- (void)setImage:(UIImage *)image;

@end

// MyCollectionViewCell.m

#import "MyCollectionViewCell.h"

@interface MyCollectionViewCell ()

@property (strong, nonatomic) UIImageView *imageView;

@end

@implementation MyCollectionViewCell

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setupImageView];
    }
    return self;
}

- (void)setupImageView
{
    UIImageView *imageView = [[UIImageView alloc]init];
    imageView.backgroundColor = [UIColor greenColor];
    [self addSubview:imageView];
    self.imageView = imageView;

    [imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
    NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
    NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
    NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
    NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];

    [self addConstraints:@[leading, trailing, top, bottom]];

}

- (void)setImage:(UIImage *)image
{
    [self.imageView setImage:image];
}

@end

这里的布局限制是关键。根据我的经验,UICollectionViewCells在初始化时通常会有一个0的框架,这就是为什么你会看到大量的空盒子(新单元格上的UIImageView正在用CGRectZero初始化)。约束将确保当它们最终正确布局时,imageView也将调整自身以适应。

在此之后,注册您的自定义单元类,然后您可以在CollectionViewController

中实现它
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
    [cell setImage:[UIImage imageNamed:@"emoji.jpg"]];
    // Configure the cell

    return cell;
}

这里是明确设置UIImageViewFrame的前后镜头

layout with frame on initWithFrame:

VS。使用NSLayoutConstraints。

layout with constraints

对于它的地狱,这里是如何在cellForItemAtIndexPath中做同样的事情。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

    NSInteger viewTag = 1000;
    UIImageView *imageView = (UIImageView *)[cell viewWithTag:viewTag];

    if (!imageView) {
        imageView = [[UIImageView alloc]init];
        imageView.tag = viewTag;
        [cell addSubview:imageView];

        [imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
        NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
        NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
        NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
        NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
        [cell addConstraints:@[leading, trailing, top, bottom]];
    }

    imageView.image = [UIImage imageNamed:@"emoji.jpg"];

    return cell;
}