我有一个的UIImageView在UICollectionView每个小区,现在我想添加复制标注,就像在Photos.app:
我看到UICollectionViewDelegate这个方法:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
研究一些额外的几分钟后,我发现UIMenuController类,因为我明白,我必须同它合作,以获得菜单,但无论如何,我认为必须有更简单的方法,然后创建UIGestureRecognizer,以及创建,定位等我UIMenu。
我在正确的轨道上? 你怎么能实现这个功能?
是的,你是在正确的轨道上。 您也可以实现超越剪切,复制自定义操作,使用这种技术贴。
对于UICollectionView自定义操作
// ViewController.h
@interface ViewController : UICollectionViewController
// ViewController.m
-(void)viewDidLoad
{
[super viewDidLoad];
self.collectionView.delegate = self;
UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Custom Action"
action:@selector(customAction:)];
[[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]];
}
#pragma mark - UICollectionViewDelegate methods
- (BOOL)collectionView:(UICollectionView *)collectionView
canPerformAction:(SEL)action
forItemAtIndexPath:(NSIndexPath *)indexPath
withSender:(id)sender {
return YES; // YES for the Cut, copy, paste actions
}
- (BOOL)collectionView:(UICollectionView *)collectionView
shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)collectionView:(UICollectionView *)collectionView
performAction:(SEL)action
forItemAtIndexPath:(NSIndexPath *)indexPath
withSender:(id)sender {
NSLog(@"performAction");
}
#pragma mark - UIMenuController required methods
- (BOOL)canBecomeFirstResponder {
// NOTE: The menu item will on iOS 6.0 without YES (May be optional on iOS 7.0)
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;
}
#pragma mark - Custom Action(s)
- (void)customAction:(id)sender {
NSLog(@"custom action! %@", sender);
}
注:的iOS 7.0更改行为
在你UICollectionViewCell子类中,你需要添加自定义操作方法,或者什么也不会出现。
// Cell.m #import "Cell.h" @implementation Cell - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // custom logic } return self; } - (void)customAction:(id)sender { NSLog(@"Hello"); if([self.delegate respondsToSelector:@selector(customAction:forCell:)]) { [self.delegate customAction:sender forCell:self]; } } @end
你需要创建一个委托协议,将其放置在每一个细胞都回调到维护您的UICollectionView的UIController。 这是因为,细胞不应该对你的模型没有什么,因为它只涉及显示内容。
// Cell.h #import <UIKit/UIKit.h> @class Cell; // Forward declare Custom Cell for the property @protocol MyMenuDelegate <NSObject> @optional - (void)customAction:(id)sender forCell:(Cell *)cell; @end @interface Cell : UICollectionViewCell @property (strong, nonatomic) UILabel* label; @property (weak, nonatomic) id<MyMenuDelegate> delegate; @end
在你UICollectionViewController的视图控制器或子类,您需要符合协议并实施新的方法。
// ViewController.m @interface ViewController () <MyMenuDelegate> @end // @implementation ViewController ... - (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; { Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"MY_CELL" forIndexPath:indexPath]; cell.delegate = self; return cell; } // ... // Delegate method for iOS 7.0 to get action from UICollectionViewCell - (void)customAction:(id)sender forCell:(Cell *)cell { NSLog(@"custom action! %@", sender); }
可选 :在你的UIView子类可以覆盖默认的剪切,复制,如果你在这里实现的方法canPerformAction,粘贴而不是在UIViewController中。 否则,行为将显示您的自定义方法之前默认的方法。
// Cell.m - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { NSLog(@"canPerformAction"); // The selector(s) should match your UIMenuItem selector NSLog(@"Sender: %@", sender); if (action == @selector(customAction:)) { return YES; } return NO; }
这是一个完整的解决方案:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
if ([NSStringFromSelector(action) isEqualToString:@"copy:"])
return YES;
else
return NO;
}
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
if ([NSStringFromSelector(action) isEqualToString:@"copy:"]) {
UIPasteboard *pasteBoard = [UIPasteboard pasteboardWithName:UIPasteboardNameGeneral create:NO];
pasteBoard.persistent = YES;
NSData *capturedImageData = UIImagePNGRepresentation([_capturedPhotos objectAtIndex:indexPath.row]);
[pasteBoard setData:capturedImageData forPasteboardType:(NSString *)kUTTypePNG];
}
}
就我而言,我只允许在我的CollectionView复印功能,如果按复印,我复制是细胞到剪贴板内的图像。
也许有点晚了,但我发现也许对于那些谁仍在寻找这更好的解决方案:
在你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 {
}