UICollectionView上的可重用性问题 [英] Reusability issue on UICollectionView

查看:199
本文介绍了UICollectionView上的可重用性问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾与 UITableView ,但我从来没有使用 UICollectionView 在我的应用程序。因此,我要以编程方式创建 UICollectionView

$



以下是我的代码:

  UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc] init]; 
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0,43,self.view.frame.size.width,self.view.frame.size.height - 84)collectionViewLayout:layout];
[_collectionView setDataSource:self];
[_collectionView setDelegate:self];
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@cellIdentifier];
layout.sectionInset = UIEdgeInsetsMake(5,5,5,5);
layout.minimumInteritemSpacing = 5;
[_collectionView setBackgroundColor:self.view.backgroundColor];
[self.view addSubview:_collectionView];

委托和数据源方法。

  #pragma mark  -  
#pragma mark - UITableView委托方法

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 15;
}

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

if(cell.selected)
cell.backgroundColor = [UIColor lightGrayColor]; // highlight selection cell
else
cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@background-grid.png]]; // Default Cell

UIImageView * imgPhoto = [[UIImageView alloc] init];
imgPhoto.userInteractionEnabled = YES;
imgPhoto.backgroundColor = [UIColor grayColor];
imgPhoto.frame = CGRectMake(3.5,5,90,80);
imgPhoto.clipsToBounds = YES;
imgPhoto.image = [UIImage imageNamed:@product.png];
[cell.contentView addSubview:imgPhoto];

UILabel * lblCategoryTitle = [[UILabel alloc] init];
[lblCategoryTitle setFont:[UIFont fontWithName:@OpenSans-Boldsize:14]];
lblCategoryTitle.textAlignment = NSTextAlignmentCenter;
lblCategoryTitle.frame = CGRectMake(3.5,90,90,24);
lblCategoryTitle.textColor = [UIColor blackColor];
lblCategoryTitle.text = @Product 1;
lblCategoryTitle.backgroundColor = [UIColor clearColor];
lblCategoryTitle.numberOfLines = 2;
[cell.contentView addSubview:lblCategoryTitle];

return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView布局:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake 97,118);
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

UICollectionViewCell * datasetCell = [collectionView cellForItemAtIndexPath:indexPath] ;
datasetCell.backgroundColor = [UIColor lightGrayColor]; // highlight selected
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {

UICollectionViewCell * datasetCell = [collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@background-grid.png]]; //默认单元格
}

然后我的屏幕看起来像



>



问题1 - 查看上述屏幕,您会看到第一个和第三个项目看起来模糊(参见产品1 /中间项?为什么会发生这种情况?



每当我向上/向下滚动 UICollectionView ,则项目会被覆盖,查看下一张图片



>



看过这张图片后,根据我的经验 UITableView ,发生的原因是 UICollectionView的单元格的可重用性



问题2 - 然后如何解决?



(建议 @Dima ) / em>

自定义单元格



.h文件



  #import< UIKit / UIKit.h> 

@interface customeGridCell:UICollectionViewCell

@property(nonatomic,strong)UIImageView * imgPhoto;
@property(nonatomic,strong)UILabel * lblCategoryTitle;

@end



.m档



  #importcustomeGridCell.h

@implementation customeGridCell

- (id)initWithFrame:(CGRect )frame
{
self = [super initWithFrame:frame];
if(self)
{
self.imgPhoto = [[UIImageView alloc] init];
self.imgPhoto.userInteractionEnabled = YES;
self.imgPhoto.backgroundColor = [UIColor grayColor];
self.imgPhoto.frame = CGRectMake(3.5,5,90,80);
[self addSubview:self.imgPhoto];

self.lblCategoryTitle = [[UILabel alloc] init];
[self.lblCategoryTitle setFont:[UIFont fontWithName:@OpenSans-Boldsize:14]];
self.lblCategoryTitle.textAlignment = NSTextAlignmentCenter;
self.lblCategoryTitle.frame = CGRectMake(3.5,90,90,24);
self.lblCategoryTitle.textColor = [UIColor blackColor];
self.lblCategoryTitle.backgroundColor = [UIColor clearColor];
self.lblCategoryTitle.numberOfLines = 2;
[self addSubview:self.lblCategoryTitle];
}
return self;
}

以及的代码cellForItemAtIndexPath

   - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{
customeGridCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@cellIdentifierforIndexPath:indexPath];

if(cell.selected)
cell.backgroundColor = [UIColor lightGrayColor]; // highlight selection cell
else
cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@background-grid.png]]; // Default Cell


cell.imgPhoto.image = [UIImage imageNamed:@product.png];
cell.lblCategoryTitle.text = @Product 1;

return cell;
}


解决方案

code> collectionView:cellForItemAtIndexPath:方法。您每次添加这些子视图一个单元格被重复使用,在彼此的顶部。



您应该创建一个 UICollectionViewCell 子类,并将所有额外的子视图添加到其初始化器。



这里是一个例子你如何子类 UICollectionViewCell

  @interface MyCustomCell :UICollectionViewCell 

@property(nonatomic,strong)UILabel * customLabel;
@property(nonatomic,strong)UIImageView * customImageView;
@end


//在实现文件中
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
//在这里初始化label和imageview,然后将它们作为子视图添加到内容视图
}
return self;
}

然后当你抓住一个单元格,你只要做一些事情:

   - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{
MyCustomCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@cellIdentifierforIndexPath:indexPath];

if(cell.selected)
cell.backgroundColor = [UIColor lightGrayColor]; // highlight selection cell
else
cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@background-grid.png]]; //默认单元格

cell.customImageView.image = //无论
cell.customLabel.text = //无论

return cell;
}


I had worked with UITableView but I have never ever use of UICollectionView in my apps. So I want to create UICollectionView programmatically.

Following is my code:

UICollectionViewFlowLayout *layout =[[UICollectionViewFlowLayout alloc] init];
    _collectionView=[[UICollectionView alloc] initWithFrame:CGRectMake(0, 43, self.view.frame.size.width, self.view.frame.size.height - 84) collectionViewLayout:layout];
    [_collectionView setDataSource:self];
    [_collectionView setDelegate:self];
    [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
    layout.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5);
    layout.minimumInteritemSpacing = 5;
    [_collectionView setBackgroundColor:self.view.backgroundColor];        
    [self.view addSubview:_collectionView];

Delegate and Datasource methods.

#pragma mark -
#pragma mark - UITableView Delegate Methods

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 15;
}

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

    if (cell.selected)
        cell.backgroundColor = [UIColor lightGrayColor]; // highlight selection cell
    else
        cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background-grid.png"]]; // Default Cell

    UIImageView *imgPhoto = [[UIImageView alloc] init];
    imgPhoto.userInteractionEnabled = YES;
    imgPhoto.backgroundColor = [UIColor grayColor];
    imgPhoto.frame =  CGRectMake(3.5, 5, 90, 80);
    imgPhoto.clipsToBounds = YES;
    imgPhoto.image = [UIImage imageNamed:@"product.png"];
    [cell.contentView addSubview:imgPhoto];

    UILabel *lblCategoryTitle = [[UILabel alloc] init];
    [lblCategoryTitle  setFont: [UIFont fontWithName:@"OpenSans-Bold" size:14]];
    lblCategoryTitle.textAlignment = NSTextAlignmentCenter;
    lblCategoryTitle.frame = CGRectMake(3.5, 90, 90, 24);
    lblCategoryTitle.textColor = [UIColor blackColor];
    lblCategoryTitle.text = @"Product 1"; 
    lblCategoryTitle.backgroundColor = [UIColor clearColor];
    lblCategoryTitle.numberOfLines = 2;
    [cell.contentView addSubview:lblCategoryTitle];

    return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(97, 118);
}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath  {

    UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
    datasetCell.backgroundColor = [UIColor lightGrayColor]; // highlight selection
}

-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {

    UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
    datasetCell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background-grid.png"]]; // default cell
}

Then my screen Look like

Question 1 - Look at above screen, you will see that 1st and 3rd item is looking blur (see Product 1 ) then 2nd/middle item ? why this is happening ?

And whenever I scroll up/down UICollectionView then items are overwrite, Look at Next image

After looked this image, from my experience of UITableView, it's happening because of Reusability of cell of UICollectionView.

Question 2 - Then how can i solve it?

Please give my your suggestion and help me on this issue.

EDITED: (suggestion of @Dima)

Custom cell

.h file

#import <UIKit/UIKit.h>

@interface customeGridCell : UICollectionViewCell

@property (nonatomic, strong) UIImageView *imgPhoto;
@property (nonatomic, strong) UILabel *lblCategoryTitle;

@end

.m file

#import "customeGridCell.h"

@implementation customeGridCell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.imgPhoto = [[UIImageView alloc] init];
        self.imgPhoto.userInteractionEnabled = YES;
        self.imgPhoto.backgroundColor = [UIColor grayColor];
        self.imgPhoto.frame =  CGRectMake(3.5, 5, 90, 80);
        [self addSubview:self.imgPhoto];

        self.lblCategoryTitle = [[UILabel alloc] init];
        [self.lblCategoryTitle  setFont: [UIFont fontWithName:@"OpenSans-Bold" size:14]];
        self.lblCategoryTitle.textAlignment = NSTextAlignmentCenter;
        self.lblCategoryTitle.frame = CGRectMake(3.5, 90, 90, 24);
        self.lblCategoryTitle.textColor = [UIColor blackColor];
        self.lblCategoryTitle.backgroundColor = [UIColor clearColor];
        self.lblCategoryTitle.numberOfLines = 2;
        [self addSubview:self.lblCategoryTitle];
    }
    return self;
}

And code of cellForItemAtIndexPath

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    customeGridCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];

    if (cell.selected)
        cell.backgroundColor = [UIColor lightGrayColor]; // highlight selection cell
    else
        cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background-grid.png"]]; // Default Cell


    cell.imgPhoto.image =  [UIImage imageNamed:@"product.png"];
    cell.lblCategoryTitle.text = @"Product 1";

    return cell;
}

解决方案

The problem is in your collectionView:cellForItemAtIndexPath: method. You are adding those subviews every single time a cell is reused, on top of each other.

You should create a UICollectionViewCell subclass and add all of the extra subviews you want into its initializer. This will make sure they only get added once.

sample code:

Here is an example of how you would subclass UICollectionViewCell

@interface MyCustomCell : UICollectionViewCell

@property (nonatomic, strong) UILabel *customLabel;
@property (nonatomic, strong) UIImageView *customImageView;
@end


// in implementation file
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // initialize label and imageview here, then add them as subviews to the content view
    }
    return self;
}

Then when you are grabbing a cell you just do something like:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MyCustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];

    if (cell.selected)
        cell.backgroundColor = [UIColor lightGrayColor]; // highlight selection cell
    else
        cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background-grid.png"]]; // Default Cell

    cell.customImageView.image = // whatever
    cell.customLabel.text = // whatever

    return cell;
}

这篇关于UICollectionView上的可重用性问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆