如何从 UICollectionViewCell 访问 UICollectionView 中 Cell 的 indexPath
Posted
技术标签:
【中文标题】如何从 UICollectionViewCell 访问 UICollectionView 中 Cell 的 indexPath【英文标题】:how to access from UICollectionViewCell the indexPath of the Cell in UICollectionView 【发布时间】:2012-12-14 08:59:23 【问题描述】:我想在调用动作时为 UICollectionViewCell
设置动画。
我在Interface Builder
中完成了UICollectionViewCell
,也完成了UICollectionView
。
现在我想在我的actionBtnAddToCard
方法中获得正确的indexPath
。
这就是我现在尝试的方式(ProduktViewCell.m 中的方法):
- (IBAction)actionAddToCart:(id)sender
XLog(@"");
// see this line
NSIndexPath *indexPath = ??** how can i access the correct indexPath**??;
SortimentViewController *svc = [[SortimentViewController alloc] initWithNibName:@"SortimentViewController_iPad" bundle:[NSBundle mainBundle]];
[svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];
[svc collectionView:svc.collectionViewProdukte didSelectItemAtIndexPath:indexPath];
SortimentViewController 是继承 UICollectionView 的 viewController。如何访问正确的 indexPath?
更新 1:编辑帖子以便更好地理解。
【问题讨论】:
看看这个 SO 答案,这是一种更优雅和简单的方式***.com/questions/13966291/… 【参考方案1】:- (IBAction)actionAddToCart:(id)sender
NSIndexPath *indexPath;
indexPath = [self.collectionView indexPathForItemAtPoint:[self.collectionView convertPoint:sender.center fromView:sender.superview]];
...
【讨论】:
【参考方案2】:如果您知道视图层次结构,这很容易。
UIButton *button = (UiButton *) sender;
如果按钮是这样的-> UITableViewCell->按钮
那么你可以得到这样的单元格
UITableViewCell *cell = (UITableViewCell *)[button superview];
如果按钮是这样的-> UITableViewCell -> 内容视图-> 按钮
UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];
最后可以像这样提取索引路径
NSIndexPath *indexPath = [self.table_View indexPathForCell:cell];
【讨论】:
是的,在集合视图的上下文中谈论你的意思时有点困惑,你介意向我们展示一个完整的动作 sn-p 吗? OP 已经要求在 UICollectionView 而不是 UITableViewCell 的情况下提供解决方案。恕我直言,这个答案向读者发送了错误信息。请编辑指出如何在 UICollectionView 中执行此操作。[[button superview] superview]
很脆弱。我在下面添加了一个更安全的答案。
UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];帮帮我。当我有:button->collectionview->UItableviewcell
很抱歉,但多次调用 superview 非常麻烦。对视图层次结构的更改很容易中断此类调用。而这个原始问题不涉及 UITableView。【参考方案3】:
不依赖于视图。 试试这个。
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:buttonPosition];
NSLog(@"%ld", (long)indexPath.row);
【讨论】:
【参考方案4】:使用像[[button superview] superview]
这样的代码是脆弱的,而且不是面向未来的;实际上,除非您明确测试它,否则它甚至不能保证适用于所有 ios 版本。为此,我总是使用迭代辅助方法:-
- (UIView *)superviewWithClassName:(NSString *)className fromView:(UIView *)view
while (view)
if ([NSStringFromClass([view class]) isEqualToString:className])
return view;
view = view.superview;
return nil;
然后我从按钮处理程序中调用它,如下所示:-
- (IBAction)buttonClicked:(id)sender
UIButton *button = (UIButton *)sender;
UICollectionViewCell *cell = (UICollectionViewCell *)
[self superviewWithClassName:@"UICollectionViewCell"
fromView:button];
if (cell)
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
// do whatever action you need with the indexPath...
更新:superviewWithClassName
的 Swift 版本。使它成为一个类方法,因为它从不引用self
。
static func superviewWithClassName(className:String, fromView view:UIView?) -> UIView?
guard let classType = NSClassFromString(className) else
return nil
var v:UIView? = view
while (v != nil)
if v!.isKindOfClass(classType)
return v
v = v!.superview
return nil
以及一些调用它的代码,来自prepareForSegue
或按钮处理程序:-
guard let cell = UIView.superviewWithClassName("UICollectionViewCell", fromView: sender as? UIView) as? UITableViewCell else return
【讨论】:
【参考方案5】:Swift 解决方案: 像这样的 UICollectionView 扩展对此很有用。
extension UICollectionView
func indexPathForView(view: AnyObject) -> NSIndexPath?
let originInCollectioView = self.convertPoint(CGPointZero, fromView: (view as! UIView))
return self.indexPathForItemAtPoint(originInCollectioView)
在任何地方都可以轻松使用。
let indexPath = collectionView.indexPathForView(button)
【讨论】:
很好的解决方案。谢谢【参考方案6】:您可以这样做,indexPathsForVisibleItems 将为当前在视图中可见的项目返回 NSIndexPaths 数组,第一个对象返回第一个(如果每个视图有一个单元格)。
NSIndexPath *indexPath = [[svc.collectionViewProdukte indexPathsForVisibleItems] firstObject]
【讨论】:
考虑添加解释【参考方案7】:如果要为特定单元格设置动画,则需要获取对该单元格的引用。只需调用
[svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];
什么都不做。您需要保留该方法返回的单元格,如下所示:
UICollectionViewCell *cell = [svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];
之后,继续制作动画:
[UIView animateWithDuration:0.2f animations:^
cell.transform = CGAffineTransformMakeScale(0.5f, 0.5f);
];
【讨论】:
但是我怎样才能得到 indexPath?我会更新我的问题以便更好地理解 indexPath 只是引用特定单元格的一种方式。在不知道您的应用做什么的情况下,我无法猜测您要为哪个单元格设置动画。 要获取第一个单元格,应该是这样的: NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; 那是我的问题。如何找出调用了哪些单元格操作? 这真的取决于你的应用程序的结构。如果每个单元格都有一个“添加到购物车”按钮,您可能会考虑将该按钮放在单元格内(应该是 UICollectionViewCell 子类),并确保按钮调用单元格本身(而不是视图控制器)上的方法.然后使用委托模式在视图控制器上调用一些逻辑方法:类似于 -(void)addToCartButtonPressedForCell:(UICollectionViewCell *)cell];【参考方案8】:Swift 3 解决方案:基于 Ishan Handa 的回答
extension UICollectionView
func indexPathForView(view: AnyObject) -> IndexPath?
let originInCollectioView = self.convert(CGPoint.zero, from: (view as! UIView))
return self.indexPathForItem(at: originInCollectioView) as IndexPath?
用法:
func deleteCell(sender:UIButton)
var indexPath:IndexPath? = nil
indexPath = self.collectionView.indexPathForView(view: sender)
print("index path : \(indexPath)")
【讨论】:
【参考方案9】://Note: this is for a storyboard implementation
// here is code for finding the row and section of a textfield being edited in a uicollectionview
UIView *contentView = (UIView *)[textField superview];
UICollectionViewCell *cell = (UICollectionViewCell *)[contentView superview];
cell = (UICollectionViewCell *)[contentView superview];
// determine indexpath for a specific cell in a uicollectionview
NSIndexPath *editPath = [myCollectionView indexPathForCell:cell];
int rowIndex = editPath.row;
int secIndex = editPath.section;
【讨论】:
【参考方案10】:尽管我在这里找到了很多答案。这将是最短且有用的,与视图层次结构无关
- (void) actionAddToCart:(id)sender
id view = [sender superview];
while (view && [view isKindOfClass:[UICollectionViewCell class]] == NO)
view = [view superview];
NSIndexPath *thisIndexPath = [self.collectionView indexPathForCell:view];
NSLog(@"%d actionAddToCart pressed",thisIndexPath.row);
【讨论】:
【参考方案11】:您几乎可以肯定有一个 UICollectionViewCell 子类。只需添加一个属性并在 cellForItemAtIndexPath 中设置 indexPath。
【讨论】:
这一直有效,直到您启用对项目的重新排序,然后您必须手动进入并修复所有受影响单元格的 indexPath 属性。【参考方案12】:Xcode10。 Swift 4.2 版本。
extension UICollectionView
func indexPathForView(view: AnyObject) -> IndexPath?
guard let view = view as? UIView else return nil
let senderIndexPath = self.convert(CGPoint.zero, from: view)
return self.indexPathForItem(at: senderIndexPath)
用法:
// yourView can be button for example
let indexPath = collectionView.indexPathForView(view: yourView)
【讨论】:
【参考方案13】: internal func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: “cell_id”, for: indexPath)
let bttn_obj = UIButton(frame: CGRect(x: 5.5, y: 5.5, width: 22, height: 22))
bttn_obj.addTarget(self, action: #selector(bttn_action), for: UIControl.Event.touchUpInside)
cell.addSubview(bttn_obj)
return cell
@IBAction func bttn_action(_ sender: UIButton) -> Void
let cell_view = sender.superview as! UICollectionViewCell
let index_p : IndexPath = self.collectionview.indexPath(for: cell_view)!
print(index_p)
【讨论】:
以上是关于如何从 UICollectionViewCell 访问 UICollectionView 中 Cell 的 indexPath的主要内容,如果未能解决你的问题,请参考以下文章
如何从自定义 UICollectionViewCell 启动 View Controller
如何从 UICollectionViewCell 访问 UICollectionView 中 Cell 的 indexPath
如何从不同的方法访问 UICollectionViewCell 中标签的文本?
如何从 UICollectionViewController 验证 UICollectionViewCell 的值