长按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也被称为
- (BOOL)canBecomeFirstResponder {
// NOTE: This menu item will not show if this is not YES!
return YES;
}
//未调用此方法
- (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;
}
我也实施了这些方法
- (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");
}
虽然它只显示“剪切,复制和粘贴”菜单
答案 0 :(得分:6)
也许有点晚了但我可能会为那些仍然在寻找它的人找到更好的解决方案:
在你的UICollectionViewController的viewDidLoad中添加你的项目:
UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Title" action:@selector(action:)];
[[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]];
添加以下委托方法:
//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;
}
如果你还没有UICollectionViewCell的子类。添加您为项目指定的方法:
- (void)action:(UIMenuController*)menuController {
}
这样您就不需要任何becomeFirstResponder或其他方法。您可以在一个地方执行所有操作,如果您将单元格本身作为参数调用一般方法,则可以轻松处理不同的单元格。
编辑:不知何故,uicollectionview需要存在此方法(此方法不会调用您的自定义操作,我认为uicollectionview只是检查是否存在)
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
}
答案 1 :(得分:5)
您需要从自定义UICollectionViewCell
触发委托函数这是我的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..
}
将以下功能添加到自定义UICollectionViewCell
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == NSSelectorFromString("editCollection") || action == NSSelectorFromString("deleteCollection")
}
从单元格调用委托函数(需要在您的自定义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)
}
答案 2 :(得分:4)
我花了两天的时间试图找出“正确”的做法,并用一些建议咆哮错误的树。
本文介绍了执行此操作的正确方法。我希望通过在这里发布,有人将被保存几个小时。
http://dev.glide.me/2013/05/custom-item-in-uimenucontroller-of.html
答案 3 :(得分:2)
Swift 3解决方案:
只需在UICollectionView类中执行所有操作,并将此类分配给UICollectionView对象。
import UIKit
class MyAppCollectionView: UICollectionView {
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
addLongPressGesture()
}
func addLongPressGesture() {
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(MyAppCollectionView.longPressed(_:)))
longPressGesture.minimumPressDuration = 0.5
self.addGestureRecognizer(longPressGesture)
}
func longPressed(_ gesture: UILongPressGestureRecognizer) {
let point = gesture.location(in: self)
let indexPath = self.indexPathForItem(at: point)
if indexPath != nil {
MyAppViewController.cellIndex = indexPath!.row
let editMenu = UIMenuController.shared
becomeFirstResponder()
let custom1Item = UIMenuItem(title: "Custom1", action: #selector(MyAppViewController.custome1Method))
let custom2Item = UIMenuItem(title: "Custom2", action: #selector(MyAppViewController.custome2Method))
editMenu.menuItems = [custom1Item, custom2Item]
editMenu.setTargetRect(CGRect(x: point.x, y: point.y, width: 20, height: 20), in: self)
editMenu.setMenuVisible(true, animated: true)
}
}
override var canBecomeFirstResponder: Bool {
return true
}
}
class MyAppViewController: UIViewController {
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
// You need to only return true for the actions you want, otherwise you get the whole range of
// iOS actions. You can see this by just removing the if statement here.
//For folder edit
if action == #selector(MyAppViewController.custome1Method) {
return true
}
if action == #selector(MyAppViewController.custome2Method) {
return true
}
return false
}
}
答案 4 :(得分:1)
如果人们在长按集合视图(或表格视图)时无法使菜单正常工作时,总是有以下两个原因之一:
您正在使用长按手势识别器进行操作。例如,您不能在同一集合视图中同时具有拖动和菜单。
您已经忘记在单元格中实现选择器 。
例如,OP的代码显示:
UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Custom Action"
action:@selector(customAction:)];
含义是customAction
是方法 this 类。这是错误。 customAction:
必须是 cell 类的方法。原因是运行时会查看单元格类,并且除非该单元格实现菜单项的操作方法,否则运行时将不会显示菜单项。
有关完整的最小工作示例(在Swift中),请在此处查看我的答案:https://stackoverflow.com/a/51898182/341994
答案 5 :(得分:0)
在 iOS 9 上使用 Swift 来显示自定义项目(没有默认剪切,粘贴等),我只能使用以下代码进行操作。
方法viewDidLoad
:
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(contextMenuHandler))
longPressRecognizer.minimumPressDuration = 0.3
longPressRecognizer.delaysTouchesBegan = true
self.collectionView?.addGestureRecognizer(longPressRecognizer)
覆盖方法canBecomeFirstResponder
:
override func canBecomeFirstResponder() -> Bool {
return true
}
覆盖这两个与集合相关的方法:
override func collectionView(collectionView: UICollectionView, shouldShowMenuForItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func collectionView(collectionView: UICollectionView, canPerformAction action: Selector,
forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool {
return (action == #selector(send) || action == #selector(delete))
}
创建手势处理程序方法:
func contextMenuHandler(gesture: UILongPressGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.Began {
let indexPath = self.collectionView?.indexPathForItemAtPoint(gesture.locationInView(self.collectionView))
if indexPath != nil {
self.selectedIndexPath = indexPath!
let cell = self.collectionView?.cellForItemAtIndexPath(self.selectedIndexPath)
let menu = UIMenuController.sharedMenuController()
let sendMenuItem = UIMenuItem(title: "Send", action: #selector(send))
let deleteMenuItem = UIMenuItem(title: "Delete", action: #selector(delete))
menu.setTargetRect(CGRectMake(0, 5, 60, 80), inView: (cell?.contentView)!)
menu.menuItems = [sendMenuItem, deleteMenuItem]
menu.setMenuVisible(true, animated: true)
}
}
}
最后,创建选择器的方法:
func send() {
print("Send performed!")
}
func delete() {
print("Delete performed!")
}
希望有所帮助。 :)
干杯。