显示UIMenuController将取消selectUITableViewCell

我已经在显示UIMenuController的表格视图单元上实现了一个长按手势识别UIMenuController 。 但是当菜单显示时,对应的表视图单元格被取消select。 在显示菜单之前,我会根据需要调用[self becomeFirstResponder] 。 我认为这个调用取消了这个单元格,但是如何让它在UIMenuController可见的时候保持选中呢?

一个简单的方法是使用特定的UITableViewDelegate方法来处理UIMenuController。 但首先,为了让单元格保持选中状态,请将存在菜单的单元格的值存储在您的类中:

 NSIndexPath *_editingIndexPath; 

然后实现UITableViewDelegateMethods:

 - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { MyCustomTableViewCell *cell = (MyCustomTableViewCell *) [_tableView cellForRowAtIndexPath:indexPath]; _editingIndexPath = indexPath; cell.showingMenu = YES; return YES; } - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { if (action == @selector(copy:)) { return YES; } return NO; } - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { if (action == @selector(copy:)) { UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; if (cell && [cell isKindOfClass:[MessageConversationCell class]]) { [UIPasteboard generalPasteboard].string = cell.textLabel.text; } } } 

上面的代码会在长时间按下后在单元上显示一个“复制”菜单。 现在,如果您希望单元格在显示菜单时保持选中状态:

在名为“showsMenu”的自定义单元格中添加@property(注意,此属性已经在此答案中的第一个代码块中设置)。

 @property (nonatomic, assign) BOOL showingMenu; 

添加(或修改,如果已经存在)下面的方法到您的自定义单元格。 在菜单试图解除亮点之后,这将保持单元格的高亮显示(您可以实现自己的逻辑来突出显示单元格,在这种情况下,将它放在if条件的第一个分支中):

 - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { if (_showingMenu) { [super setHighlighted:YES] } else { [super setHighlighted:highlighted]; } } 

添加一个观察者,当菜单将要被提示时被通知。 这进入视图控制器,而不是在自定义单元格中:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didShowEditMenu:) name:UIMenuControllerDidShowMenuNotification object:nil]; 

在视图控制器上添加菜单显示时要调用的方法:

 - (void)didShowEditMenu:(NSNotification *)not { [_tableView selectRowAtIndexPath:_editingIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; MyCustomTableViewCell *cell = (MyCustomTableViewCell*)[_conversationTableView cellForRowAtIndexPath:_editingIndexPath]; cell.showingMenu = NO; } 

不要忘记在不再需要的时候移除观察者:

 [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerDidShowMenuNotification object:nil]; 

当单元格被长时间按下时,这将显示一个菜单,并保持单元格被选中,直到菜单消失,或者是因为select了一个选项,或者是因为用户点击了其他地方。 它与WhatsApp在select邮件时的工作方式非常相似。

在你的UITableViewDelegate ,覆盖tableView:willDeselectRowAtIndexPath:当你不希望你的行取消select时,根据文档返回nil

你说你正在调用[self becomeFirstResponder]但是你的问题并没有指出自己是哪个对象。 我想self是你的控制者。 您应该将becomeFirstResponder消息发送到产生becomeFirstResponder的UITableViewCell。

 - (void)longPress:(UILongPressGestureRecognizer *)recognizer { if (recognizer.state == UIGestureRecognizerStateBegan) { TSTableViewCell *cell = (TSTableViewCell *)recognizer.view; //This is your problem [cell becomeFirstResponder]; UIMenuItem *flag = [[UIMenuItem alloc] initWithTitle:@"Flag" action:@selector(flag:)]; UIMenuItem *approve = [[UIMenuItem alloc] initWithTitle:@"Approve" action:@selector(approve:)]; UIMenuItem *deny = [[UIMenuItem alloc] initWithTitle:@"Deny" action:@selector(deny:)]; UIMenuController *menu = [UIMenuController sharedMenuController]; [menu setMenuItems:[NSArray arrayWithObjects:flag, approve, deny, nil]]; [menu setTargetRect:cell.frame inView:cell.superview]; [menu setMenuVisible:YES animated:YES]; } } 

我find了这个解决scheme:

 - (void)handleLongPress:(UILongPressGestureRecognizer *)longPressRecognizer { if (longPressRecognizer.state == UIGestureRecognizerStateBegan) { UITableViewCell *cell = (UITableViewCell *)longPressRecognizer.view; [cell setSelected:YES]; ... } }