从自定义 UICollectionViewCell 获取正确的按钮
Get correct button from custom 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];
但是结果还是错误
因为您没有为单元格中的按钮设置标签。所以这些都是 select 一次编辑的。您可以将他们的标签设置为 indexPath.item 并在 didSelectItemAtIndexPath 和 select 中捕获他们的标签所需的项目。
您可以在选择器中设置按钮标签和检索标签。
- (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;
}
为您的按钮分配一个标签以识别它。
- (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];
}
注意:实现multiple/single选择的最佳方法是通过与您的喜好关联的 ID。使用集合视图存储该 ID,然后从按钮方法重新加载 table。
如果您还需要更多帮助,请告诉我..
基本思路是,您需要将按钮坐标 space 转换为集合视图坐标 space,然后检索 indexPath。
如果您需要使用 Objective-C,让我们创建一个 returns 给定单元格子视图的 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 的问题。
有类似问题here and here
问题是由于 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
}
就是这样,如果你想反转同样删除索引路径的操作
我有一个带有自定义 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];
但是结果还是错误
您可以在选择器中设置按钮标签和检索标签。
- (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;
}
为您的按钮分配一个标签以识别它。
- (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];
}
注意:实现multiple/single选择的最佳方法是通过与您的喜好关联的 ID。使用集合视图存储该 ID,然后从按钮方法重新加载 table。
如果您还需要更多帮助,请告诉我..
基本思路是,您需要将按钮坐标 space 转换为集合视图坐标 space,然后检索 indexPath。
如果您需要使用 Objective-C,让我们创建一个 returns 给定单元格子视图的 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 的问题。
有类似问题here and here
问题是由于 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
}
就是这样,如果你想反转同样删除索引路径的操作