2011-01-03 43 views
5

Tôi có một UITableViewController. Tôi muốn bật menu sao chép/dán lên khi người dùng chạm vào một ô. Tôi muốn làm như trong ứng dụng Danh bạ. Cách triển khai chức năng này. Ai đó có thể giúp tôi.Chức năng sao chép/dán trong UITableViewController

Tôi đã thử mã này,

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

Nhưng nó không hoạt động. Câu hỏi của tôi là,

  1. CGRect nào tôi phải chuyển thành tham số setTargetRect?
  2. Tôi có cần gọi SetNeedsDisplayInRect trong TableViewController không?
  3. Điều gì khác cần làm để thực hiện công việc này?

Trả lời

7

Nếu tôi không sai Trình đơn sao chép/dán xuất hiện khi nhấn và giữ một ô trong liên hệ phải không? Nếu vậy, tôi sẽ sử dụng lớp UILongPressGestureRecognizer để có được báo chí dài trong ô.

về

1: pass rect của tế bào và inView: pass UITableView bạn

2: Tôi không nghĩ là cần thiết

3: không có gì hơn:

Something như thế này sẽ hoạt động ...

- (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]; 
    } 

} 

Lưu ý: Mã trên là bộ não được biên soạn

Hy vọng điều đó sẽ giúp;)

+0

@ nacho4d: Cảm ơn câu trả lời của bạn. Lớp của tôi là UITableViewController. SO tôi đặt "[theMenu setTargetRect: cell.frame inView: [self view]]". Nhưng nó không hoạt động. Tôi đã thử [tableView tự], một lần nữa nó không hoạt động. Tôi phải đặt cái gì ở đó? – EmptyStack

+0

@ nacho4d: UIMenuControllerWillShowMenuNotification đang kích hoạt đúng cách. Tôi không chắc chắn nó hiển thị hay không? Nhưng nó không nhìn thấy được. Làm thế nào để làm cho nó có thể nhìn thấy? – EmptyStack

+0

@ nacho4d: Tôi đã in x, y, chiều rộng và chiều cao của menuFrame. Hiển thị 0 cho chiều rộng.Tôi thiết lập nó đúng trong phương thức setTargetRect: inView: Nhưng chiều rộng được hiển thị 0 khi in nó. Bất kỳ ý tưởng tại sao điều này xảy ra? – EmptyStack

2

01Tập lớp con UITableViewCell và triển khai chức năng sao chép có ý tưởng hay. Tôi khuyên bạn nên có một cái nhìn vào lớp CopyableCell. Here là liên kết GitHub. Hy vọng nó giúp.

+1

Ahmet, cảm ơn công việc của bạn, đã gửi những thay đổi của tôi cho bạn qua email. –

2

Tôi đã thực hiện một số cải tiến đối với công việc của Ahmet. Dưới đây là kết quả các lớp:

/* 
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 

Dưới đây là file * .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 

Đây là lớp helper tiêu đề:

#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 

Thực hiện:

#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 
Các vấn đề liên quan