Ios UICollectionView中重复使用的单元格显示多个UIImageView,而它们只应显示一个
我的Ios UICollectionView中重复使用的单元格显示多个UIImageView,而它们只应显示一个,ios,objective-c,uiimage,uicollectionview,Ios,Objective C,Uiimage,Uicollectionview,我的UICollectionView有问题。最初,它显示精细,显示单元格网格,每个单元格都有一个UIImageView。这些uiImageView显示了存储在应用程序包中的透明PNG 我的问题是,一旦滚动了UICollectionView,一些单元格似乎已损坏 损坏的单元格显示多个堆叠在一起的图像,最上面的图像是它应该显示的图像,下面的图像是应该在其他单元格中使用的图像 我最好的猜测是,这与UICollectionView中的单元格的重用方式有关,但我愿意接受建议 这是我用于在UICollect
UICollectionView
有问题。最初,它显示精细,显示单元格网格,每个单元格都有一个UIImageView
。这些uiImageView
显示了存储在应用程序包中的透明PNG
我的问题是,一旦滚动了UICollectionView
,一些单元格似乎已损坏
损坏的单元格显示多个堆叠在一起的图像,最上面的图像是它应该显示的图像,下面的图像是应该在其他单元格中使用的图像
我最好的猜测是,这与UICollectionView
中的单元格的重用方式有关,但我愿意接受建议
这是我用于在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;
}
如果需要,我可以提供更多的代码
如何阻止单元格损坏?问题是,您不断向
UICollectionViewCell
添加视图,因为它们被UICollectionView
自动重用。因此,当调用cellForItemAtIndexPath:
时,旧的UIImageView
仍在单元格中,因为您正在添加一个
不要使用addSubview:
相反,您可以创建一个自定义单元格,其中包含您想要的所有视图。因此,当调用cellForItemAtIndexPath:
时,您只需设置此CustomCollectionViewCell的内容即可
这样它肯定会停止被破坏
如何构建自定义单元格 步骤1:创建.h和.m类 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
步骤2:导入它!
现在我们已经创建了CustomCell,我们可以将它导入到我们想要使用它的类中
步骤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;
}
步骤4:将单元格注册到collectionView
在viewDidLoad/loadView中添加以下行:
[_collectionView registerClass:[CustomCell class] forCellWithReuseIdentifier:@"CustomCell"];
步骤5:尽情享受吧!
您的自定义单元格已完成。现在做你想做的事,别忘了也喝点咖啡。这是因为你每次在你的单元格中添加一个
UIImageView
来解决这个问题,你必须制作一个自定义单元格,然后像take一样使用它:
自定义.h
#import <UIKit/UIKit.h>
@interface CustomCell : UICollectionViewCell
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
您的控制器
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"CustomCell" forIndexPath:indexPath];
NSString * buttonPath=[[NSBundle mainBundle] pathForResource:@"button" ofType:@"png" inDirectory:[[buttons objectAtIndex:indexPath.row] objectForKey:@"name"]];
UIImage * button=[UIImage imageWithContentsOfFile:buttonPath];
[cell.imageView setImage:button];
return cell;
}
您还必须将类似“CustomCell”的标识符设置为IB中的单元格
UICollectionViewCell * cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
加上这一行,
[[[cell contentView] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
对于以编程方式添加UICollectionView并具有自定义单元格(换句话说,没有XIB文件)的任何人,您必须将此行添加到viewDidLoad
[_collectionView registerClass:[CustomCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
用于从uicollectionviewcell中的标签中删除重复文本
// Viewdidload
[_collectionView registerClass:[UICollectionviewcell class] forCellWithReuseIdentifier:@"cellIdentifier"];
//in this method create label like this
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellidentifier" forIndexPath:indexPath];
for (UILabel *lbl in cell.contentView.subviews)
{
if ([lbl isKindOfClass:[UILabel class]])
{
[lbl removeFromSuperview];
}
}
UILabel *nameLbl=[[UILabel alloc] initWithFrame:CGRectMake(0, 10, 50, 20)];
nameLbl.text=[Array objectAtIndex:indexpath.row];
nameLbl.textColor=[UIColor whiteColor];
[cell.contentView addSubview:nameLbl];
return cell;
}
对于那些正在寻找快速答案的人,请将此函数添加到您的
CustomCell
类中:
override func prepareForReuse() {
contentView.subviews.forEach({ $0.removeFromSuperview() })
// replace contentView with the superview of the repeating content.
}
你是对的,这正是你重复使用细胞的方式。因为您只是使用addSubview:calls在单元格上一层接一层地添加。您能演示一下如何实现CustomerCollectionViewCell吗?当然可以。你想在事先知道故事板或纯代码的情况下完成吗?我也讨厌在故事板中这样做:P无论如何,这应该是纯代码中的。如果一切都清楚,请告诉我。啊,你需要继续投下牢房。^^现在请稍等。可能还应该生成返回值(CustomCell*)。我在这里,直到这是正确的,所以我得到你需要的答案!只要不在cellForItemAtIndexPath:函数中执行此操作。CustomCell完全可以为您自己的设计定制。此“自定义”单元格及其内部的所有内容正被系统正确地重新使用。这是删除它们的方法,但不应生成它们,因此您无需删除它们。当上一个集合视图单元格内容具有子视图,并且您希望删除该子视图并添加新的子视图时,此功能非常有用。当您将其设置为图像视图时,会出现这种情况。请描述您发布的内容!原因是什么?此外,它也不起作用:(这对我来说非常有效。对于初学者来说,这意味着您必须将覆盖功能添加到您连接插座的swift文件中。请参见
class DeviceCollectionViewCell:UICollectionViewCell{@IBOutlet弱var设备名称:UILabel!@IBOutlet弱var功能:UILabel!@IBOutlet弱var品牌标签:UILabel!@IBOutlet弱var SVGIconview:UIView!重写func prepareForReuse(){SVGIconview.subviews.forEach({$0.removeFromSuperview()}}
你救了我一天!非常感谢!
[_collectionView registerClass:[CustomCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
// Viewdidload
[_collectionView registerClass:[UICollectionviewcell class] forCellWithReuseIdentifier:@"cellIdentifier"];
//in this method create label like this
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellidentifier" forIndexPath:indexPath];
for (UILabel *lbl in cell.contentView.subviews)
{
if ([lbl isKindOfClass:[UILabel class]])
{
[lbl removeFromSuperview];
}
}
UILabel *nameLbl=[[UILabel alloc] initWithFrame:CGRectMake(0, 10, 50, 20)];
nameLbl.text=[Array objectAtIndex:indexpath.row];
nameLbl.textColor=[UIColor whiteColor];
[cell.contentView addSubview:nameLbl];
return cell;
}
override func prepareForReuse() {
contentView.subviews.forEach({ $0.removeFromSuperview() })
// replace contentView with the superview of the repeating content.
}