将 UIButton 添加到 UICollectionViewCell 时的奇怪行为

Posted

技术标签:

【中文标题】将 UIButton 添加到 UICollectionViewCell 时的奇怪行为【英文标题】:Strange behavior when adding UIButton to UICollectionViewCell 【发布时间】:2015-05-19 03:45:23 【问题描述】:

我正在尝试将 aUIButton 添加到 aUICollectionViewCell。该按钮的主要目的是让用户选择他们最喜欢的。

当他们点击UIButton 时,UIButton 将显示一个发光的星形图像,表明该项目已被选为收藏夹。

再次点击UIButton,按钮返回显示原图,带空星,表示取消选择。

我的实现方式如下:

1 - 在情节提要中,将 UIButton 放入UICollectionViewCell,按住 ctrl 并拖动按钮到单元格的 .h 文件以设置名为

的操作
-(IBAction)favoriteBtnClick:(id)sender;

2 - 在单元格的 .m 文件中,按如下方式编辑操作:

-(IBAction)favoriteBtnClick:(id)sender 
    if ([self.favoriteChecked isEqualToString:@"NO"]) 
        UIImage *image = [UIImage imageNamed:@"FavoriteSelected.PNG"];
        [sender setBackgroundImage:image forState:UIControlStateNormal];
        self.favoriteChecked = @"YES";
     else if ([self.favoriteChecked isEqualToString:@"YES"]) 
        UIImage *image = [UIImage imageNamed:@"FavoriteBlank.PNG"];
        [sender setBackgroundImage:image forState:UIControlStateNormal];
        

但是,当我尝试运行UICollectionView 时,当我单击一个单元格上的按钮时,发生了“奇怪”的行为:

1 - 向下滚动列表后,单击一个单元格可将一个按钮变为最喜欢的发光星星,下面一些其他单元格上的按钮也会变为选中状态。

2 - 切换仅在一个周期内起作用。完成第一轮选择和取消选择后,进一步点击不再有反应。

谁能帮我理解这个问题的原因,并可能给我一些关于如何解决它的提示?

谢谢!

问候, 保罗

【问题讨论】:

这是由于单元重用而发生的。可以显示cellForItemAtIndexPath方法代码吗? 非常感谢大家。刚刚解决了这个问题。实际上,我从这里的所有建议中得到了答案。首先,使用convertPoint to View方法识别collectionView上cell的indexPath。然后更新数据模型对象中的收藏状态。最后要求collectionView重新加载数据。问题解决了!很酷! 【参考方案1】:

在您的按钮操作中添加此代码

CGPoint ButtonPoint = [sender convertPoint:CGPointZero toView:self.collectionView];
    NSIndexPath *ButtonIndex = [self.collectionView indexPathForItemAtPoint:ButtonPoint];
buttonindexpath = ButtonIndex.row
[collectionView reloadData];

现在在您的 cellForItemAtIndexPath 中,检查 indexPath.row == buttonindexpath,如果是,请给出您在按钮操作中提供的代码...。 即....

if (indexPath.row == buttonindexpath)

    if ([self.favoriteChecked isEqualToString:@"NO"]) 
    
        UIImage *image = [UIImage imageNamed:@"FavoriteSelected.PNG"];
        [sender setBackgroundImage:image forState:UIControlStateNormal];
        self.favoriteChecked = @"YES";
    
    else if ([self.favoriteChecked isEqualToString:@"YES"]) 
    
        UIImage *image = [UIImage imageNamed:@"FavoriteBlank.PNG"];
        [sender setBackgroundImage:image forState:UIControlStateNormal];
    

希望一切顺利

【讨论】:

您的回答可能会有所帮助,但看起来您必须对其进行编辑,因为 OP 正在询问 UICollectionView 并且答案代码是 UITableView。请编辑您的答案, @Balram Tiwari,我已经编辑了集合视图的代码。很抱歉将其误认为是表格视图。希望这段代码能正常工作【参考方案2】:

发生这种情况是因为细胞重复使用。因为self.favoriteChecked 是自定义集合单元类中的一个属性,并且它的值仅在该类中更新会导致此问题。

此问题的解决方案是,如果您使用自定义对象模型从视图控制器填充集合单元格,则在收藏按钮上单击更新该自定义对象上的收藏状态,并在 cellForItemAtIndexPath 方法中检查收藏状态的值并更新自定义collectionviewcell类的favoriteChecked状态。

如果您不使用自定义对象,则需要分别保存最喜欢项目的列表,无论是最喜欢项目的索引路径还是最喜欢项目的唯一标识符。然后在cellForItemAtIndexPath方法中检查收藏状态的值并更新自定义collectionviewcell类的favoriteChecked状态。

【讨论】:

【参考方案3】:

这不是什么奇怪的行为。您已从模型数据对象加载单元格。您必须在数组中跟踪并保持按钮单击数据的状态变化,然后加载单元格数据值。

这是一个示例代码:它与您的问题的解决方案一致。

NSMutableArray *favoriteStatusArray = [[NSMutableArray alloc]init];
// assume favoriteStatusArray is initialized with all BOOL as NO.

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


    SomeCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    cell.favoriteButton.tag = indexPath.row;
    [cell.favoriteButton addTarget:self action:@selector(peformFavoriteChange:) forControlEvents:UIControlEventTouchUpInside];

    if([[favoriteStatusArray objectAtIndex:indexPath.row] boolValue] == NO)
        UIImage *image = [UIImage imageNamed:@"FavoriteSelected.PNG"];
        [cell.favoriteButton setBackgroundImage:image forState:UIControlStateNormal];
    else     
    UIImage *image = [UIImage imageNamed:@"FavoriteBlank.PNG"];
    [cell.favoriteButton setBackgroundImage:image forState:UIControlStateNormal];    
   
    return cell;



-(void)peformFavoriteChange:(UIButton *)sender

    BOOL oldValue = [[favoriteStatusArray objectAtIndex:sender.tag] boolValue];
    [favoriteStatusArray replaceObjectAtIndex:sender.tag withObject:[NSNumber numberWithBool:!oldValue]];

    [myCollectionView reloadData]; 

希望你有这样做的想法。

【讨论】:

以上是关于将 UIButton 添加到 UICollectionViewCell 时的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

如果将 UIButton 作为子视图添加到 UIImageView,则单击 UIButton 不起作用

将 UIButton 动态添加到 UITableViewCell 错误

将 UIButton 添加到 UICollectionViewCell 时的奇怪行为

将 CAShapeLayer 添加到 UIButton 不起作用

以编程方式将 UIButton 添加到 UITableView 错误点

如何将 UIButton 添加到 Swift Playground?