显示 UIMenuController 取消选择 UITableViewCell
Posted
技术标签:
【中文标题】显示 UIMenuController 取消选择 UITableViewCell【英文标题】:Showing UIMenuController deselects UITableViewCell 【发布时间】:2013-01-22 15:06:00 【问题描述】:我在显示UIMenuController
的表格视图单元格上实现了长按手势识别器。但是当菜单显示时,相应的表格视图单元格会取消选择。在显示菜单之前,我会根据需要拨打[self becomeFirstResponder]
。我认为这个调用会取消选择单元格,但是如何使它在 UIMenuController
可见时保持选中状态?
【问题讨论】:
【参考方案1】:根据the documentation,在您的UITableViewDelegate
中,当您不想取消选择行时,覆盖tableView:willDeselectRowAtIndexPath:
并返回nil
。
【讨论】:
【参考方案2】:实现这一点的更简单方法是使用特定的 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;
上面的代码将负责在长按后在单元格上显示“复制”菜单。 现在,如果您希望在显示菜单时单元格保持选中状态:
在名为“showingMenu”的自定义单元格中添加一个@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];
这将在长按单元格时显示一个菜单,并保持该单元格处于选中状态,直到菜单消失,因为选择了一个选项或因为用户点击了其他地方。当您选择消息时,它的工作方式与 Whatsapp 的工作方式非常相似。
【讨论】:
【参考方案3】:您说您正在调用[self becomeFirstResponder]
,但您的问题并未表明 self 是哪个对象。我猜self
是你的控制器。您应该将becomeFirstResponder
消息发送到生成 UIMenuController 的 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];
【讨论】:
【参考方案4】:我找到了这个解决方案:
- (void)handleLongPress:(UILongPressGestureRecognizer *)longPressRecognizer
if (longPressRecognizer.state == UIGestureRecognizerStateBegan)
UITableViewCell *cell = (UITableViewCell *)longPressRecognizer.view;
[cell setSelected:YES];
...
【讨论】:
以上是关于显示 UIMenuController 取消选择 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章