UICollectionView 中重用的单元格在应该只显示一个时显示多个 UIImageView [英] Reused cells in a UICollectionView show multiple UIImageViews when they should only show one

查看:10
本文介绍了UICollectionView 中重用的单元格在应该只显示一个时显示多个 UIImageView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 UICollectionView 有问题.最初它显示良好,显示一个单元格网格,每个单元格都有一个 UIImageView.这些 UIImageViews 显示存储在应用程序包中的具有透明度的 PNG.

Im having a problem with my UICollectionView. Initially it displays fine, showing a grid of cells, each cell with a single UIImageView. These UIImageViews are showing PNGs with transparency that are stored in the app's bundle.

我的问题是,一旦滚动 UICollectionView,一些单元格似乎已损坏.

My problem is, once the UICollectionView has been scrolled, some of the cells seem to be corrupt.

一个损坏的单元格显示了多个堆叠在一起的图像,最上面的图像是它应该显示的图像,下面的图像是应该在其他单元格中使用的图像.

A corrupt cell shows multiple images stacked on top of each other, the top most image is the one it should be showing, and images underneath are the ones that should be used in other cells.

我最好的猜测是,这与 UICollectionView 中的单元格被重用的方式有关,但我愿意接受建议.

My best guess is that this has something to do with the way cells inside a UICollectionView are reused, but I am open to suggestions.

这是我用于在 UICollectionView 中创建单元格的委托代码:

This is the delegate code I use for creating cells within the UICollectionView:

// creates the individual cells to go in the menu view
- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    // create collection view cell
    UICollectionViewCell * cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];

    // create a uiview where we can place all views that need to go into this cell
    UIView * contents=[[UIView alloc] initWithFrame:cell.contentView.bounds];
    [contents setBackgroundColor:[UIColor clearColor]];
    [cell.contentView addSubview:contents];

    // add a button image
    NSString * buttonPath=[[NSBundle mainBundle] pathForResource:@"button" ofType:@"png" inDirectory:[[buttons objectAtIndex:indexPath.row] objectForKey:@"name"]];
    UIImage * button=[UIImage imageWithContentsOfFile:buttonPath];
    UIImageView * buttonView=[[UIImageView alloc] initWithImage:button];
    [buttonView setContentMode:UIViewContentModeScaleAspectFit];
    [buttonView setFrame:contents.bounds];
    [contents addSubview:buttonView];

    // set tag to the indexPath.row so we can access it later
    [cell setTag:indexPath.row];

    // add interactivity
    UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onButtonTapped:)];
    [tap setNumberOfTapsRequired:1];
    [cell addGestureRecognizer:tap];

    // return the cell
    return cell;

}

如果需要,我可以提供更多代码.

I can provide more code if required.

如何阻止单元格损坏?

推荐答案

问题是你一直在向 UICollectionViewCell 添加视图,因为它们被 UICollectionView.所以旧的 UIImageView 仍然在单元格上,因为您在调用 cellForItemAtIndexPath: 时又添加了一个.

The problem is that you keep adding views to the UICollectionViewCell as they are being reused automagically by the UICollectionView. So the old UIImageView's are still on the cell as you are adding one more as the cellForItemAtIndexPath: is called.

不要使用 addSubview:

相反,您可以创建一个自定义单元格,其中包含您想要的所有视图.这样当调用 cellForItemAtIndexPath: 时,您只需设置此 CustomCollectionViewCell 的内容即可.

Instead you could make a custom cell with all the views you want already in them. So that when the cellForItemAtIndexPath: is called you only need to set the contents of this CustomCollectionViewCell instead.

这样它肯定不会被破坏.

This way it will certainly stop being corrupted.

如何构建 CustomCell.

How to build a CustomCell.

第 1 步:创建 .h &.m 类.

Step1: Create the .h & .m class.

CustomCell.h

CustomCell.h

#import <UIKit/UIKit.h>

@interface CustomCell : UICollectionViewCell
{
    UIImageView *imageView;
}

@property (nonatomic, retain) UIImageView *imageView; //this imageview is the only thing we need right now.

@end

CustomCell.m

CustomCell.m

#import "CustomCell.h"

@implementation CustomCell

@synthesize imageView;

- (id)initWithFrame:(CGRect)aRect
{
    if (self = [super initWithFrame:aRect])
    {
         //we create the UIImageView in this overwritten init so that we always have it at hand.
         imageView = [UIImageView alloc] init];
         //set specs and special wants for the imageView here.
         [self addSubview:imageView]; //the only place we want to do this addSubview: is here!

         //You wanted the imageView to react to touches and gestures. We can do that here too.
         UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onButtonTapped:)];
        [tap setNumberOfTapsRequired:1];
        [self addGestureRecognizer:tap];


        //We can also prepare views with additional contents here!
        //just add more labels/views/whatever you want.
    }
    return self;
}

-(void)onButtonTapped:(id)sender
{
    //the response to the gesture.
    //mind that this is done in the cell. If you don't want things to happen from this cell.
    //then you can still activate this the way you did in your question.

}

第二步:导入!现在我们创建了 CustomCell,我们可以将它导入到我们想要使用它的类中.

Step2: Import it! Now that we created the CustomCell we can import it in the class we want to use it in.

第 3 步:在行动中使用它!

// creates the individual cells to go in the menu view
- (CustomCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    // create collection view cell
    CustomCell *cell = (CustomCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"CustomCell" forIndexPath:indexPath]; //this is the place where the CustomCell does his magic.
    //Make sure to use the CustomCellReuseId that you register in the viewdidload/loadview (step4)

    // add a button image
    NSString * buttonPath=[[NSBundle mainBundle] pathForResource:@"button" ofType:@"png" inDirectory:[[buttons objectAtIndex:indexPath.row] objectForKey:@"name"]];

    cell.imageView.image = [UIImage imageWithContentsOfFile:buttonPath]; //place the image on the CustemCell.imageView as we prepared.

    // set tag to the indexPath.row so we can access it later
    [cell setTag:indexPath.row]; //we don't need this to access the cell but I left this in for your personal want.

/*
 * we can now do this from the CustomCell as well!
 *
    // add interactivity
    UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onButtonTapped:)];
    [tap setNumberOfTapsRequired:1];
    [cell addGestureRecognizer:tap];
*/
    // return the cell
    return cell;

}

Step4:将cell注册到collectionView

Step4: Register the cell to the collectionView

在viewDidLoad/loadView中添加这一行:

in the viewDidLoad / loadView add this line:

[_collectionView registerClass:[CustomCell class] forCellWithReuseIdentifier:@"CustomCell"];

第五步:尽情享受吧!您的 CustomCell 已完成.现在做任何你喜欢的事,别忘了也喝点咖啡.

Step5: Enjoy! Your CustomCell is done. Now do whatever you like and don't forget to get some coffee too.

这篇关于UICollectionView 中重用的单元格在应该只显示一个时显示多个 UIImageView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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