Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIMenuController with custom item not working with UICollectionview

I have added custom menu controller when long press on UICollectionViewCell

    [self becomeFirstResponder];
    UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Custom Action"
                                                      action:@selector(customAction:)];
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]];
    [[UIMenuController sharedMenuController] setTargetRect: self.frame inView:self.superview];
    [[UIMenuController sharedMenuController] setMenuVisible:YES animated: YES];

canBecomeFirstResponder Is also being called

- (BOOL)canBecomeFirstResponder {
    // NOTE: This menu item will not show if this is not YES!
    return YES;
}

//This method is not being called

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    NSLog(@"canPerformAction");
    // The selector(s) should match your UIMenuItem selector
    if (action == @selector(customAction:)) {
        return YES;
    }
    return NO;
}

I have Also Implemented these methods

- (BOOL)collectionView:(UICollectionView *)collectionView
      canPerformAction:(SEL)action
    forItemAtIndexPath:(NSIndexPath *)indexPath
            withSender:(id)sender {


    if([NSStringFromSelector(action) isEqualToString:@"customAction:"]){
        NSLog(@"indexpath : %@",indexPath);
        UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"warning.." message:@"Do you really want to delete this photo?" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
        [alertview show];
        return YES;
    }

    return YES;

}

- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

- (void)collectionView:(UICollectionView *)collectionView
         performAction:(SEL)action
    forItemAtIndexPath:(NSIndexPath *)indexPath
            withSender:(id)sender {
    NSLog(@"performAction");
}

Though it is showing only "cut, copy, and paste" menus

like image 202
Heena Avatar asked Jun 10 '13 13:06

Heena


3 Answers

Maybe a bit late but i maybe found a better solution for those who are still search for this:

In viewDidLoad of your UICollectionViewController add your item:

UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Title" action:@selector(action:)];
[[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]];

Add the following delegate methods:

//This method is called instead of canPerformAction for each action (copy, cut and paste too)
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
        if (action == @selector(action:)) {
            return YES;
        }
        return NO;
    }
    //Yes for showing menu in general
    - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
        return YES;
    }

Subclass UICollectionViewCell if you didn't already. Add the method you specified for your item:

- (void)action:(UIMenuController*)menuController {

}

This way you don't need any becomeFirstResponder or other methods. You have all actions in one place and you can easily handle different cells if you call a general method with the cell itself as a parameter.

Edit: Somehow the uicollectionview needs the existence of this method (this method isn't called for your custom action, i think the uicollectionview just checks for existance)

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {

}
like image 188
Nilz11 Avatar answered Nov 18 '22 03:11

Nilz11


You need to trigger delegate functions from custom UICollectionViewCell

Here is my working sample code for Swift3

CollectionViewController

override func viewDidLoad() {
    super.viewDidLoad()
    let editMenuItem = UIMenuItem(title: "Edit", action: NSSelectorFromString("editCollection"))
    let deleteMenuItem = UIMenuItem(title: "Delete", action: NSSelectorFromString("deleteCollection"))
    UIMenuController.shared.menuItems = [editMenuItem, deleteMenuItem]

}

override func collectionView(_ collectionView: UICollectionView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool {
    return true
}

override func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
    return action == NSSelectorFromString("editCollection") || action == NSSelectorFromString("deleteCollection")
}

override func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) {
    print("action:\(action.description)")
    //Custom actions here..
}

Add following functions to your custom UICollectionViewCell

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return action == NSSelectorFromString("editCollection") || action == NSSelectorFromString("deleteCollection")
}

To call delegate function from cell (needs to be in your custom UICollectionViewCell)

func editCollection()
{
    let collectionView = self.superview as! UICollectionView
    let d:UICollectionViewDelegate = collectionView.delegate!
    d.collectionView!(collectionView, performAction: NSSelectorFromString("editCollection"), forItemAt: collectionView.indexPath(for: self)!, withSender: self)
}
func deleteCollection()
{
    let collectionView = self.superview as! UICollectionView
    let d:UICollectionViewDelegate = collectionView.delegate!
    d.collectionView!(collectionView, performAction: NSSelectorFromString("deleteCollection"), forItemAt: collectionView.indexPath(for: self)!, withSender: self)
}
like image 6
ayalcin Avatar answered Nov 18 '22 01:11

ayalcin


I've just spent two days trying to figure out the "correct" way of doing this, and barking up the wrong tree with some of the suggestions that are around.

This article shows the correct way of doing this. I hope that by posting it here someone will be saved a few hours.

http://dev.glide.me/2013/05/custom-item-in-uimenucontroller-of.html

like image 4
RegularExpression Avatar answered Nov 18 '22 03:11

RegularExpression