je veux animer le UICollectionViewCell
quand l'action est appelée.
J'ai fait UICollectionViewCell
dans Interface Builder
, le UICollectionView
également . Maintenant, je veux obtenir le indexPath
correct à ma méthode actionBtnAddToCard
.
c’est ce que j’essaie maintenant (méthode dans 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 est le viewController qui hérite de UICollectionView.
comment accéder au bon indexPath?
UPDATE 1: publication modifiée pour une meilleure compréhension.
si vous connaissez la hiérarchie des vues, c'est facile.
UIButton *button = (UiButton *) sender;
si le bouton est comme ceci -> UITableViewCell -> bouton
alors vous pouvez obtenir une cellule comme celle-ci
UITableViewCell *cell = (UITableViewCell *)[button superview];
si le bouton est comme ceci -> UITableViewCell -> affichage du contenu -> bouton
UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];
et enfin le chemin de l'index peut être extrait comme ça
NSIndexPath *indexPath = [self.table_View indexPathForCell:cell];
- (IBAction)actionAddToCart:(id)sender {
NSIndexPath *indexPath;
indexPath = [self.collectionView indexPathForItemAtPoint:[self.collectionView convertPoint:sender.center fromView:sender.superview]];
...
}
Ne comptez pas sur la vue ... Essayez ceci.
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:buttonPosition];
NSLog(@"%ld", (long)indexPath.row);
L'utilisation d'un code tel que [[button superview] superview]
est fragile et non pérenne; en effet, il n'est même pas garanti de fonctionner sur toutes les versions d'iOS, à moins que vous ne le testiez explicitement. J'utilise toujours une méthode d'assistance itérative à cette fin: -
- (UIView *)superviewWithClassName:(NSString *)className fromView:(UIView *)view
{
while (view)
{
if ([NSStringFromClass([view class]) isEqualToString:className])
{
return view;
}
view = view.superview;
}
return nil;
}
Ensuite, je l'appelle depuis le gestionnaire de boutons, comme suit: -
- (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...
}
}
UPDATE: Version rapide de superviewWithClassName
. Faites-en une méthode de classe car elle ne fait jamais référence à 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
}
et du code pour l'appeler, à partir de prepareForSegue
ou d'un gestionnaire de boutons: -
guard let cell = UIView.superviewWithClassName("UICollectionViewCell", fromView: sender as? UIView) as? UITableViewCell else {return}
Swift solution: Une extension UICollectionView comme celle-ci peut être utile à cet effet.
extension UICollectionView {
func indexPathForView(view: AnyObject) -> NSIndexPath? {
let originInCollectioView = self.convertPoint(CGPointZero, fromView: (view as! UIView))
return self.indexPathForItemAtPoint(originInCollectioView)
}
}
L'utilisation devient facile partout.
let indexPath = collectionView.indexPathForView(button)
Si vous souhaitez animer une cellule spécifique, vous devez obtenir une référence à cette cellule. Appeler simplement
[svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];
ne fait rien. Vous devez conserver la cellule renvoyée par la méthode, comme ceci:
UICollectionViewCell *cell = [svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];
Après cela, allez-y et animez:
[UIView animateWithDuration:0.2f animations:^{
cell.transform = CGAffineTransformMakeScale(0.5f, 0.5f);
}];
Vous pouvez le faire comme ceci, indexPathsForVisibleItems retournera un tableau de NSIndexPaths pour les éléments actuellement visibles et le premier objet retournera le premier (si vous avez une cellule par vue).
NSIndexPath *indexPath = [[svc.collectionViewProdukte indexPathsForVisibleItems] firstObject]
Swift 3 Solution: basée sur la réponse d'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?
}
}
Usage:
func deleteCell(sender:UIButton){
var indexPath:IndexPath? = nil
indexPath = self.collectionView.indexPathForView(view: sender)
print("index path : \(indexPath)")
}
//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;
Même si beaucoup de réponses que j'ai trouvées ici, ce sera le plus court et utile quelle que soit la hiérarchie des vues.
- (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);
}
Xcode10. Swift version 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)
}
}
Usage:
// yourView can be button for example
let indexPath = collectionView.indexPathForView(view: yourView)
Vous avez presque certainement une sous-classe UICollectionViewCell. Ajoutez simplement une propriété et définissez indexPath dans cellForItemAtIndexPath.