UICollectionView自定义单元格在滚动时自动刷新

时间:2013-12-04 16:52:13

标签: ios iphone objective-c uicollectionview uicollectionviewcell

我有UICollectionView和自定义UICollectionViewCell,我正在加载图片,当我滚动UICollectionView时,我看到所有单元格都在刷新,这里是代码UICollectionView 代表

ViewDidLoad中添加第一个用于添加CustomCell

 -(void)ViewdidLoad{
      UINib *nib = [UINib nibWithNibName:@"NMCFAIPadWishListCell" bundle:nil];
     [self.accountDetailsCollectionView registerNib:nib forCellWithReuseIdentifier:@"Cell"];
  }

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
      return [[self wishListData] count];

}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

static NSString *identifier = @"Cell";

       NMCFAIPadWishListCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
      [cell setWishList:[[self wishListData] objectAtIndex:[indexPath row]] delegate:self];
      return cell;
}

setWishList 方法中,只需将数组中的值分配给标签,我在自定义Xib中的每个单元格中都有一个UICollectionViewCell按钮,当用户点击该按钮时按钮我只是更改标签BG颜色

 - (void)setWishList:(NSString*)product delegate:(id)delegate
{
      self.label.text = product;
}

以下是按钮操作

- (IBAction)editProduct:(id)sender
{
      self.label.backgroundColor = [UIColor redColor];
}

我的问题是当我滚动自定义单元格并点击任何单元格中的按钮时,标签BG不仅会在当前单元格中更改,还会在多个单元格中更改。

4 个答案:

答案 0 :(得分:1)

您不应尝试在单元格中/单元格中存储任何状态,因为单元格对象本身可以由UICollectionView自行决定重复使用。

您的问题的一个解决方案可能是:

  • 在您的editProduct:方法中(假设您的editProduct:方法位于自定义UICollectionViewCell实施中),请通知集合视图的控制器用户已通过协议方法“选择”该产品(或阻止或其他一些消息传递机制)。
  • 在您的视图控制器中,当收到上述消息时,请确定已点击按钮的单元格的索引(indexPathForCell:在此处可能有用)并存储索引处的项目的事实n 已被选中。 NSArray在这里可能很有用。
  • 在同一方法中,强制重新加载已使用reloadItemsAtIndexPaths:或类似方法点击的单元格。这将强制调用collectionView:cellForRowAtIndexPath:方法。
  • collectionView:cellForRowAtIndexPath:方法中实施以下内容:

    BOOL itemSelected = ((NSNumber *)isProductSelectedArray[indexPath.row]).boolValue; // You can't store `BOOL`s directly into NSArrays. So I've assumed an NSNumber here.
    cell.backgroundColor = itemSelected ? [UIColor redColor] : [UIColor clearColor] // Or some other color to indicate non-selection.
    

顺便说一句,如果您声明“ViewdidLoad”而不是“viewDidLoad”,您可能会发现您的代码行为不符合您的预期。不要忘记在实现中的某个地方调用[super viewDidLoad]。

最后,我建议通过阅读Apple的“适用于iOS的集合视图编程指南”的“Collection View Basics”章节来更好地处理单元重用的概念 - 特别是标题为“可重用视图提高性能”的部分。

答案 1 :(得分:0)

细胞正在重复使用,因为它们令人耳目一新。

答案 2 :(得分:0)

CollectionView重用单元格,因此背景颜色的多次更改是正确的行为。

要解决您的问题,请按如下方式自定义您的UICollectionViewCell(NMCFAIPadWishListCell)实例:

UIView *backgroundView = [[UIView alloc] initWithFrame:self.bounds];
backgroundView.backgroundColor = [UIColor clearColor];
self.backgroundView = backgroundView;

UIView *selectedBGView = [[UIView alloc] initWithFrame:self.bounds];
selectedBGView.backgroundColor = [UIColor redColor];
self.selectedBackgroundView = selectedBGView;

使用委托方法进行额外选择行为:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath 
{
    // Instead of button actions, use this delegate method
}

查看UICollectionViewCell Reference了解详情。 UICollectionViewCell有三个属性 backgroundView selectedBackgroundView selected ,足以满足您的需求。

答案 3 :(得分:0)

细胞不维持状态。对应于单元格的对象数组应该主要处于状态,因为单元格经常被回收。例如,在你的cellForItemAtIndexPath:

里面
....

BOOL isWishListSet = self.isWishListSetArray[indexPath.row];
UIColor *cellColor = [UIColor redColor];
if (isWishListSet) {
    cellColor = [UIColor blackColor];
}
cell.backgroundColor = cellColor;

....

编辑1:

正如gavdotnet在他的回答中提到的,单元状态应该保持在并行数组中,而不是单元格本身。因此,您将拥有一个数组来保存您想要显示的数据,另一个数组保存该单元格是否已被选中的状态:

@interface WishListViewController ()

@property (nonatomic, strong) NSArray *wishListData;
@property (nonatomic, strong) NSMutableArray *wishListStatus;

@end

@implementation WishListViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Initialize arrays
    self.wishListData = [NSArray array];
    self.wishListStatus = [NSMutableArray array];
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.wishListData.count;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    NSNumber *isWishListSet = self.wishListStatus[indexPath.row];
    UIColor *cellColor = [UIColor redColor];
    if (isWishListSet.boolValue) {
        cellColor = [UIColor blackColor];
    }
    cell.backgroundColor = cellColor;
    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    NSNumber *isWishListSet = self.wishListStatus[indexPath.row];
    if (isWishListSet.boolValue) {
        isWishListSet = [NSNumber numberWithBool:NO];
    } else {
        isWishListSet = [NSNumber numberWithBool:YES];
    }
    [self.wishListStatus replaceObjectAtIndex:indexPath.row withObject:isWishListSet];
    UIColor *cellColor = [UIColor redColor];
    if (isWishListSet.boolValue) {
        cellColor = [UIColor blackColor];
    }
    cell.backgroundColor = cellColor;
}

部分

UIColor *cellColor = [UIColor redColor];
if (isWishListSet.boolValue) {
    cellColor = [UIColor blackColor];
}
cell.backgroundColor = cellColor;

重复,所以它应该是自己的方法,但这取决于你真的决定。该示例显示了填充单元格的数据数组,以及保存单元格状态的wishListStatus数组。如果我们不打算将细胞出列,那么这不是问题。但由于我们处于这种情况,因此必须在单元格之外保持状态。

您正在使用的行:

[cell setWishList:[[self wishListData] objectAtIndex:[indexPath row]] delegate:self];

应改为:

[cell setDelegate:self];

因为委托永远不会被切换,并且总是被设置为'self'。