2

我已经在显示UIMenuController. 但是当菜单显示时,相应的表格视图单元格会取消选择。在显示菜单之前,我会根据需要调用[self becomeFirstResponder]. 我认为这个调用取消选择单元格,但是如何使它在UIMenuController可见时保持选中状态?

4

4 回答 4

4

根据文档,当您不想取消选择行时,在您的UITableViewDelegate, 中覆盖tableView:willDeselectRowAtIndexPath:并返回。nil

于 2013-01-24T20:19:59.287 回答
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 的工作方式非常相似。

于 2013-05-30T04:50:30.717 回答
1

您说您正在打电话[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];    
    }
}
于 2013-01-24T20:28:54.987 回答
1

我找到了这个解决方案:

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

        UITableViewCell *cell = (UITableViewCell *)longPressRecognizer.view;

        [cell setSelected:YES];

        ...        
    }
}         
于 2013-01-26T13:27:32.783 回答