从自定义UICollectionViewCell获取正确的按钮

时间:2015-06-05 10:40:31

标签: objective-c uicollectionview uicollectionviewcell

我有一个带有自定义UICollectionViewCell的自定义UICollectionView,我的单元格上有一个类似的按钮(已连接到CustomCVCell.h文件),我需要在按下时更改此按钮的背景。我所做的是在cellForItemAtIndexPath:方法上声明按钮的动作,如下所示:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

    // Configure the cell
    FolderProducts *item = _feedItems[indexPath.item];

    [cell.like addTarget:self action:@selector(likeProduct:) forControlEvents:UIControlEventTouchUpInside];

    return cell;
}

然后在按钮操作上我尝试更改背景:

- (void)likeProduct:(UIButton *)button {
        [button setImage:[UIImage imageNamed:@"dislike.png"] forState:UIControlStateNormal];
}

它有效但是其他随机单元格的按钮的图像已经改变,我无法理解为什么......

我还尝试使用以下方法检索正确的单元格:

CollectionViewCell *cell = (CollectionViewCell *)button.superview.superview;

然后:

[button setImage:[UIImage imageNamed:@"dislike.png"] forState:UIControlStateNormal];

但结果仍然是错误的

5 个答案:

答案 0 :(得分:2)

基本思路是你需要将按钮坐标空间转换为集合视图坐标空间,然后检索indexPath。

如果需要使用Objective-C,我们创建一个返回给定单元子视图的indexPath的函数:

- (NSIndexPath *)indexPathForCellContainingView:(UIView *)view inCollectionView:(UICollectionView *)collectionView {
    CGPoint viewCenterRelativeToCollectionView = [collectionView convertPoint:CGPointMake(CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds)) fromView:view];
    NSIndexPath *cellIndexPath = [collectionView indexPathForItemAtPoint:viewCenterRelativeToCollectionView];
    return cellIndexPath
}

现在在你的按钮处理程序中:

- (void)likeProduct:(UIButton *)button {
    [button setImage:[UIImage imageNamed:@"dislike.png"] forState:UIControlStateNormal];
    NSIndexPath *buttonIndexPath = [self indexPathForCellContainingView:button];
    UICollectionViewCell *tappedCell = [collectionView cellForItemAtIndexPath:buttonIndexPath];
}

请记住,当您的单元格滚出界限时,它将被重用,因此您肯定需要跟踪此状态。要么将它保存到磁盘,要么你有一个简单的NSDictionary来管理每个按钮的状态。

我在Swift中有一个方便的Gist,它也完全解决了UICollectionView和UITableView的问题。

类似问题herehere

答案 1 :(得分:2)

问题是由reusing of the collection view cell导致的,因为你正在获得具有相同图像的随机按钮

解决方法是维护数组并存储liked按钮的选定索引路径

例如,你可以这样做

CustomCVCell.h

中定义自定义删除
 #import <UIKit/UIKit.h>

 @class CustomCVCell; //forword decleration
 @protocol CustomCellDelegate <NSObject>  
  - (void)customCell:(CustomCVCell *)cell actionForButton:(UIButton *)inButton; //hear u are passing the cell and the button
 @end


 @interface CustomCVCell : UICollectionViewCell
 @property (weak, nonatomic) IBOutlet UIButton *like ; //a button with outlet
 @property (weak, nonatomic) id<CustomCellDelegate> cellDelegate;// define a custom delegate
 - (IBAction)likeProduct:(UIButton *)sender; // set action to cell not in the controller 

//... other code
 @end

并在CustomCVCell.m

#import "CustomCVCell.h"

@implementation CustomCVCell

- (id)initWithFrame:(CGRect)frame
{
   self = [CustomCVCell cell];
   if (self)
   {

   }
   return self;
}

- (void)awakeFromNib {
    // Initialization code
 }

//handle button action in the cell
- (IBAction)likeProduct:(UIButton *)sender
{
   //this action you want it to be in controller, call a delegate method
   if([self.cellDelegate respondsToSelector:@selector(customCell:actionForButton:)])
   {
      [self.cellDelegate customCell:self actionForButton:sender]; //implent the action in the controller 
   }
}

@end

并在controller

- (void)viewDidLoad
 {
   [super viewDidLoad];

   UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc]init];
    //..set up code
   [_aCollectionView registerClass:[CustomCVCell class] forCellWithReuseIdentifier:@"CELL"];

   likedCells = [[NSMutableArray  alloc]init]; //to hold the index paths of the liked cells
 }

//..other code

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

  CustomCVCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath];
  if([likedCells containsObject:indexPath]) //based on the indexaths paths u can set the images of the liked cell and if not set nil
  {
     [cell.like setBackgroundImage:[UIImage imageNamed:@"22.jpg"] forState:UIControlStateNormal];
  }
  else
  {
     [cell.like setBackgroundImage:nil forState:UIControlStateNormal];
  }
  cell.backgroundColor = [UIColor greenColor]; //for testing
  cell.cellDelegate = self; //this must be important
  return cell;
}

//as the like button cliks this method will trigger since u are passing the cell and the button, u can get the index path of the cell 
- (void)customCell:(CustomCVCell *)cell actionForButton:(UIButton *)inButton
{
 //hear u will get both cell and its button
 //[inButton setImage:[UIImage imageNamed:@"22.jpg"] forState:UIControlStateNormal];
 [inButton setBackgroundImage:[UIImage imageNamed:@"22.jpg"] forState:UIControlStateNormal]; //set the image
 [likedCells addObject: [_aCollectionView indexPathForCell:cell]]; //and store the index path in the likedCells array
}

如果您想要反向移动索引路径

,那就是它

答案 2 :(得分:0)

enter image description here,因为您没有为单元格中的按钮设置标记。所以这些都是一次性选中的。您可以设置像indexPath.item这样的标记,并在didSelectItemAtIndexPath中捕获它们的标记,然后选择所需的项目。

答案 3 :(得分:0)

您可以设置按钮&amp;标签。在选择器中检索标记。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView    cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

    // Configure the cell
    FolderProducts *item = _feedItems[indexPath.item];

    cell.like.tag = indexPath.item

    [cell.like addTarget:self action:@selector(likeProduct:) forControlEvents:UIControlEventTouchUpInside];

    return cell;

} 

答案 4 :(得分:0)

为按钮指定标签以识别它。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

    // Configure the cell
    FolderProducts *item = _feedItems[indexPath.item];

    [cell.like addTarget:self action:@selector(likeProduct:) forControlEvents:UIControlEventTouchUpInside];
cell.like.tag = indexPath.item;

    return cell;
}

然后在实现方法中添加以下代码,

- (void)likeProduct:(UIButton *)button {
        UIButton *btn = (UIButton *)sender;
        [button setImage:[UIImage imageNamed:@"dislike.png"] forState:UIControlStateNormal];
}

注意:实现多项/单项选择的最佳方式是通过与您的喜欢相关联的ID。使用集合视图存储该id,然后从按钮方法重新加载表。

如果您还需要更多帮助,请告诉我。