21

我想为何UICollectionViewCell时调用动作制作动画。
我已经做过UICollectionViewCellInterface BuilderUICollectionView也。现在我想indexPath在我的actionBtnAddToCard方法中得到正确的。

这就是我现在尝试的方式(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:编辑帖子以便更好地理解。

4

13 回答 13

25
- (IBAction)actionAddToCart:(id)sender {
   NSIndexPath *indexPath;
   indexPath = [self.collectionView indexPathForItemAtPoint:[self.collectionView convertPoint:sender.center fromView:sender.superview]]; 
   ...
}
于 2013-04-29T12:50:32.457 回答
16

如果您知道视图层次结构,这很容易。

UIButton *button = (UiButton *) sender;

如果按钮是这样 -> UITableViewCell -> 按钮

然后你可以像这样得到细胞

UITableViewCell *cell = (UITableViewCell *)[button superview];

如果按钮是这样 -> UITableViewCell -> 内容视图 -> 按钮

UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];

最后可以像这样提取索引路径

NSIndexPath *indexPath = [self.table_View indexPathForCell:cell];
于 2012-12-14T09:40:11.903 回答
7

不要依赖视图。试试这个。

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:buttonPosition];

NSLog(@"%ld", (long)indexPath.row);
于 2015-02-23T13:59:21.233 回答
6

使用类似的代码[[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...
    }
}

更新:Swift 版本的superviewWithClassName. 使它成为一个类方法,因为它从不引用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}
于 2015-04-27T16:53:52.127 回答
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)
于 2016-08-20T22:37:32.513 回答
3

您可以这样做,indexPathsForVisibleItems 将为当前在视图中可见的项目返回 NSIndexPaths 数组,第一个对象返回第一个(如果每个视图有一个单元格)。

NSIndexPath *indexPath = [[svc.collectionViewProdukte indexPathsForVisibleItems] firstObject]
于 2015-03-18T22:16:26.093 回答
2

如果要为特定单元格设置动画,则需要获取对该单元格的引用。只需调用

[svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];

什么也没做。您需要保留该方法返回的单元格,如下所示:

UICollectionViewCell *cell = [svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];

之后,继续制作动画:

[UIView animateWithDuration:0.2f animations:^{
    cell.transform = CGAffineTransformMakeScale(0.5f, 0.5f);
}];
于 2012-12-14T09:10:32.430 回答
2

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)")
}
于 2016-11-22T16:59:50.113 回答
1
//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;
于 2014-07-31T18:40:52.340 回答
1

尽管我在这里找到了很多答案。无论视图层次结构如何,这都是最短且有用的

- (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);
}
于 2016-02-25T12:13:34.300 回答
0

你几乎肯定有一个 UICollectionViewCell 子类。只需添加一个属性并在 cellForItemAtIndexPath 中设置 indexPath。

于 2015-12-07T06:13:53.960 回答
0

Xcode10。斯威夫特 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) 
于 2018-10-01T13:45:02.997 回答
0
 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)
 
}
于 2021-06-24T17:40:45.880 回答