可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm making an iphone app similar to the Messages app that comes on the phone. I just set up the ability to copy messages via a UIMenuController, but if the keyboard is showing and someone tries to copy a message, the keyboard goes away (presumably because of my [cell becomeFirstResponder];
where cell
is the message cell being copied).
Is there a way to show the Copy message without losing the keyboard?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath { //...other cell setup stuff... UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showCopyDialog:)]; [cell addGestureRecognizer:longPressGesture]; return cell; } - (void)showCopyDialog:(UILongPressGestureRecognizer *)gesture { if (gesture.state == UIGestureRecognizerStateBegan) { ConvoMessageCell *cell = (ConvoMessageCell *)[gesture view]; NSIndexPath *indexPath = [self.tblConvo indexPathForCell:cell]; UIMenuController *theMenu = [UIMenuController sharedMenuController]; [cell becomeFirstResponder]; [theMenu setTargetRect:CGRectMake(menuX, menuY, 100, 100) inView:cell]; [theMenu setMenuVisible:YES animated:YES]; } }
回答1:
I solved this dilemma by subclassing UITextView to provide a way to override the nextResponder and disable the built-in actions (Paste), like so:
@interface CustomResponderTextView : UITextView @property (nonatomic, weak) UIResponder *overrideNextResponder; @end
@implementation CustomResponderTextView @synthesize overrideNextResponder; - (UIResponder *)nextResponder { if (overrideNextResponder != nil) return overrideNextResponder; else return [super nextResponder]; } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (overrideNextResponder != nil) return NO; else return [super canPerformAction:action withSender:sender]; } @end
Then, in your gesture action handler, check whether the text view is already the first responder. If so, have it override the next responder; otherwise the keyboard is probably hidden anyway and you can simply becomeFirstResponder
. You'll also have to reset the override when the menu hides:
if ([inputView isFirstResponder]) { inputView.overrideNextResponder = self; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuDidHide:) name:UIMenuControllerDidHideMenuNotification object:nil]; } else { [self becomeFirstResponder]; } - (void)menuDidHide:(NSNotification*)notification { inputView.overrideNextResponder = nil; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerDidHideMenuNotification object:nil]; }
Using the table view delegate methods introduced in iOS 5 (shouldShowMenuForRowAtIndexPath
etc.) wasn't a solution for me as I needed control over the positioning of the menu (by default it's simply horizontally centered over the cell, but I'm displaying message bubbles and wanted the menu centered over the actual bubble).
回答2:
In iOS 5, you can now use the table view delegate methods to show the Menu Controller:
- (BOOL) tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender; - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;
Showing the Menu Controller in this manner will not resign the keyboard.
I'm still curious about this though as I have an app that supports pre-iOS 5 that I would like to do what you're saying also (not resign the keyboard when the copy menu appears).