2011-01-03 20 views
5

私はUITableViewControllerを持っています。ユーザーがセルに触れると、コピー/貼り付けメニューがポップアップします。私は連絡先アプリのようにしたい。この機能を実装する方法。誰かが私を助けることができる?UITableViewControllerのコピー/ペースト機能

私は、このコードを試してみました

UIMenuController *theMenu = [UIMenuController sharedMenuController]; 
[theMenu setTargetRect:CGRectMake(10, 200, 100, 40) inView:[self tableView]]; 
[theMenu setMenuVisible:YES animated:YES]; 

しかし、それは動作しません。私の質問は、

  1. です。どのCGRectをsetTargetRectパラメータとして渡す必要がありますか?
  2. TableViewControllerでSetNeedsDisplayInRectを呼び出す必要がありますか?
  3. これを行うにはほかに何が必要ですか?

答えて

7

間違っていない場合は、連絡先のセルを長押ししても[コピー/貼り付け]メニューが表示されますか?もしそうなら、私はUILongPressGestureRecognizerクラスを使用して、セルの長押しを取得します。

1に関する

は:セルとのInViewのRECTを渡す:渡すあなたのUITableView

2:何よりも::

何か私は考えていない

3が必要ですこのように動作するはずです...

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"MyCellIdentifier"; 
    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithReuseIdentifier:CellIdentifier] autorelease]; 
     cell.accessoryType = UITableViewCellAccessoryNone; 
    cell.indentationWidth = cell.frame.size.height; 

    UILongPressGestureRecognizer *r = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(cellWasLongPressed:)]; 
    [cell addGestureRecognizer:r]; 
    [r release]; 
    } 

    //configure your cell here 
    cell.textLabel.text = [file nameForCell]; 
    return cell; 
} 

- (void)cellWasLongPressed:(UILongPressGestureRecognizer *)recognizer{ 

    if (recognizer.state == UIGestureRecognizerStateRecognized) { 
     //show your UIMenuHere 
     UITableViewCell *cell = (UITableViewCell *)recognizer.view; 
     UIMenuController *theMenu = [UIMenuController sharedMenuController]; 
     [theMenu setTargetRect:cell.frame inView:tableView]; 
     [theMenu setMenuVisible:YES animated:YES]; 
    } 

} 

注:上記のコード脳は

をコンパイルされていることがお役に立てば幸いです。

+0

@ nacho4d:お返事ありがとうございます。私のクラスはUITableViewControllerです。私は "[theMenu setTargetRect:cell.frame inView:[self view]]"を設定しました。しかし、それは動作しません。私は[self tableView]を試しましたが、再び動作しません。私はそこに設定しなければならないビューは何ですか? – EmptyStack

+0

@ nacho4d:UIMenuControllerWillShowMenuNotificationが適切に起動しています。私はその表示かどうか分からないのですか?しかし、それは見えません。それを見えるようにするには? – EmptyStack

+0

@ nacho4d:menuFrameのx、y、幅、高さを印刷しました。その幅は0です。私はsetTargetRect:inView:メソッドで正しく設定しています。しかし、印刷すると幅が0になります。なぜこのようなことが起こるのか? – EmptyStack

2

サブクラスのUITableViewCell)と良いアイデアがあるコピー機能を実装します。 CopyableCellクラスをご覧になることをお勧めします。 HereはGitHubリンクです。それが役に立てば幸い。

+1

あなたの仕事のおかげで、Ahmetさんから電子メールで私の変更が送付されました。 –

2

私はAhmetの仕事にいくつかの改良を加えました。ここで結果ているクラス:ここ

/* 
Copyright 2011 Ahmet Ardal 

Licensed under the Apache License, Version 2.0 (the "License"); 
you may not use this file except in compliance with the License. 
You may obtain a copy of the License at 

http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
See the License for the specific language governing permissions and 
limitations under the License. 
*/ 

/* 
Improved by Yuriy Umanets <[email protected]> 

Changes: 
- added new property customMenus, which is array of NamedAction instances describing names and selector action 
for each of custom menus (not one of those copy, paste, etc). The class using CopyableCell can provide own actions 
and they will be called by CopyableCell. This is implemented with dynamicMethodIMP() and resolveInstanceMethod(); 

- oldStyle field that saves old style of the cell before changing (highlighting) so that when action is taken old 
style is set back to the cell without changing behaviour expected by author; 
- (fix) in touchEnded() one needs to call [super touchEnded] in order to provide correct behaviour. 
*/ 


#import "CopyableCell.h" 
#import "NamedAction.h" 

static const CFTimeInterval kLongPressMinimumDurationSeconds = 0.5; 

@interface CopyableCell(Private) 
- (void) initialize; 
- (void) menuWillHide:(NSNotification *)notification; 
- (void) menuWillShow:(NSNotification *)notification; 
- (void) handleLongPress:(UILongPressGestureRecognizer *)longPressRecognizer; 
@end 

@implementation CopyableCell 

@synthesize data, indexPath, delegate, customMenus; 

- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
{ 
     if (!(self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) 
       return self; 

     [self initialize]; 
     return self; 
} 

- (void) initialize 
{ 
     self.data = nil; 
     self.indexPath = nil; 
     self.delegate = nil; 
     self.customMenus = nil; 
     self.selectionStyle = UITableViewCellSelectionStyleNone; 

     UILongPressGestureRecognizer *recognizer = 
     [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; 
     [recognizer setMinimumPressDuration:kLongPressMinimumDurationSeconds]; 
     [self addGestureRecognizer:recognizer]; 
     [recognizer release]; 
} 

- (void) setSelected:(BOOL)selected animated:(BOOL)animated 
{ 
     [super setSelected:selected animated:animated]; 
} 

- (void) dealloc 
{ 
     [self.customMenus release]; 
     [self.data release]; 
     [self.indexPath release]; 
     [super dealloc]; 
} 

#pragma mark - 
#pragma mark Copy Menu related methods 

- (BOOL) isCustomActionExists:(SEL)sel 
{ 
     if (self.customMenus != nil) { 
       for (int i = 0; i < customMenus.count; i++) { 
         NamedAction *namedItem = [customMenus objectAtIndex:i]; 
         if (sel == namedItem.action) 
           return YES; 
       } 
     } 
     return NO; 
} 

- (BOOL) canPerformAction:(SEL)action withSender:(id)sender 
{ 
     if (self.customMenus != nil) { 
       if ([self isCustomActionExists:action]) 
         return YES; 
     } else { 
       if (action == @selector(copy:)) 
         return YES; 
     } 
     return [super canPerformAction:action withSender:sender]; 
} 

- (void) copyToPastboard:(NSString *)dataText 
{ 
     [[UIPasteboard generalPasteboard] setString:dataText]; 
     [self resignFirstResponder]; 
} 

- (void) copy:(id)sender 
{ 
     if ((self.delegate != nil) && 
      [self.delegate respondsToSelector:@selector(copyableCell:dataForCellAtIndexPath:)]) { 
       NSString *dataText = [self.delegate copyableCell:self dataForCellAtIndexPath:self.indexPath]; 
       [self copyToPastboard:dataText]; 
     } else if (self.data != nil) { 
       [self copyToPastboard:self.data]; 
     } 
} 

- (BOOL) canBecomeFirstResponder 
{ 
     return YES; 
} 

- (BOOL) becomeFirstResponder 
{ 
     return [super becomeFirstResponder]; 
} 

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
     [super touchesEnded:touches withEvent:event]; 
     if ([self isFirstResponder] == NO) 
       return; 

     UIMenuController *menu = [UIMenuController sharedMenuController]; 
     [menu setMenuVisible:NO animated:YES]; 
     [menu update]; 
     [self resignFirstResponder]; 
} 

- (void) menuWillHide:(NSNotification *)notification 
{ 
     if ((self.delegate != nil) && [self.delegate respondsToSelector:@selector(copyableCell:deselectCellAtIndexPath:)]) 
       [self.delegate copyableCell:self deselectCellAtIndexPath:self.indexPath]; 

     self.selectionStyle = oldStyle; 
     [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerWillHideMenuNotification object:nil]; 
} 

- (void) menuWillShow:(NSNotification *)notification 
{ 
     oldStyle = self.selectionStyle; 
     self.selectionStyle = UITableViewCellSelectionStyleBlue; 
     if ((self.delegate != nil) && [self.delegate respondsToSelector:@selector(copyableCell:selectCellAtIndexPath:)]) 
       [self.delegate copyableCell:self selectCellAtIndexPath:self.indexPath]; 

     [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerWillShowMenuNotification object:nil]; 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(menuWillHide:) 
                name:UIMenuControllerWillHideMenuNotification 
                object:nil]; 
} 

#pragma mark - 
#pragma mark UILongPressGestureRecognizer Handler Methods 

#include <objc/runtime.h> 

void dynamicMethodIMP(id self, SEL sel) { 
     if ([self isCustomActionExists:sel]) 
       [((CopyableCell *)self).delegate performSelector:sel withObject:self withObject:nil]; 
} 

+ (BOOL) resolveInstanceMethod:(SEL)sel { 
     class_addMethod([self class], sel, (IMP)dynamicMethodIMP, "[email protected]:"); 
     return YES; 
} 

- (void) handleLongPress:(UILongPressGestureRecognizer *)longPressRecognizer 
{ 
     if (longPressRecognizer.state != UIGestureRecognizerStateBegan) 
       return; 

     if ([self becomeFirstResponder] == NO) 
       return; 

     UIMenuController *menu = [UIMenuController sharedMenuController]; 
     [menu setTargetRect:self.bounds inView:self]; 

     NSMutableArray *menuItems = nil; 

     if (self.customMenus != nil && customMenus.count > 0) { 
       menuItems = [[[NSMutableArray alloc] init] autorelease]; 
       for (int i = 0; i < customMenus.count; i++) { 
         NamedAction *namedItem = [customMenus objectAtIndex:i]; 
         UIMenuItem *emailItem = [[UIMenuItem alloc] initWithTitle:namedItem.name 
                      action:namedItem.action]; 
         [menuItems addObject:[emailItem autorelease]]; 
       } 
     } 
     menu.menuItems = menuItems; 

     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(menuWillShow:) 
                name:UIMenuControllerWillShowMenuNotification 
                object:nil]; 
     [menu setMenuVisible:YES animated:YES]; 
} 

@end 

は* .hファイルである:ここでは

/* 
Copyright 2011 Ahmet Ardal 

Licensed under the Apache License, Version 2.0 (the "License"); 
you may not use this file except in compliance with the License. 
You may obtain a copy of the License at 

http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
See the License for the specific language governing permissions and 
limitations under the License. 
*/ 


#import <UIKit/UIKit.h> 

@protocol CopyableCellDelegate; 

@interface CopyableCell: UITableViewCell 
{ 
     NSString *data; 
     NSArray *customMenus; 
     NSIndexPath *indexPath; 
     UITableViewCellSelectionStyle oldStyle; 
} 

@property (nonatomic, retain) NSString *data; 
@property (nonatomic, retain) NSArray *customMenus; 
@property (nonatomic, retain) NSIndexPath *indexPath; 
@property (nonatomic, assign) id<CopyableCellDelegate> delegate; 

- (void) copyToPastboard:(NSString *)dataText; 

@end 

@protocol CopyableCellDelegate<NSObject> 
@required 
- (void) copyableCell:(CopyableCell *)cell selectCellAtIndexPath:(NSIndexPath *)indexPath; 
- (void) copyableCell:(CopyableCell *)cell deselectCellAtIndexPath:(NSIndexPath *)indexPath; 

@optional 
- (NSString *) copyableCell:(CopyableCell *)cell dataForCellAtIndexPath:(NSIndexPath *)indexPath; 
@end 

は、ヘルパークラスのヘッダーです:

#import <Foundation/Foundation.h> 

@interface NamedAction : NSObject { 
     NSString *name; 
     SEL action; 
} 

@property (nonatomic, retain) NSString *name; 
@property (nonatomic, assign) SEL action; 

- (id)initWithName:(NSString *)_name action:(SEL)_action; 

@end 

実装:

#import "NamedAction.h" 

@implementation NamedAction 

@synthesize name, action; 

- (id)initWithName:(NSString *)_name action:(SEL)_action 
{ 
     if (self = [super init]) { 
       self.name = _name; 
       self.action = _action; 
     } 
     return self; 
} 

- (void)dealloc { 
     self.name = NULL; 
     self.action = NULL; 
     [super dealloc]; 
} 

@end 
関連する問題