を表示するテーブルビューセルに長押しジェスチャレコグナイザーを実装しましたUIMenuController
。ただし、メニューが表示されると、対応するテーブルビューセルの選択が解除されます。メニューを表示する前に、必要に応じてを呼び出します[self becomeFirstResponder]
。この呼び出しはセルの選択を解除すると思いますが、が表示されている間、セルを選択したままにする方法UIMenuController
はありますか?
4 に答える
ドキュメントによると、で、行の選択を解除したくない場合はUITableViewDelegate
、オーバーライドtableView:willDeselectRowAtIndexPath:
して戻ります。nil
これを実装する簡単な方法は、UIMenuControllerを処理するための特定のUITableViewDelegateメソッドを使用することです。ただし、最初に、セルを選択したままにするには、メニューを表示しているセルの値をクラスに保存します。
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];
メニューが表示されたときに呼び出されるメソッドをViewControllerに追加します。
- (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が機能するのとほとんど同じように機能します。
あなたはあなたが呼んでいると言いますが[self becomeFirstResponder]
、あなたの質問は自分自身がどのオブジェクトであるかを示していません。私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];
}
}
私はこの解決策を見つけました:
- (void)handleLongPress:(UILongPressGestureRecognizer *)longPressRecognizer
{
if (longPressRecognizer.state == UIGestureRecognizerStateBegan) {
UITableViewCell *cell = (UITableViewCell *)longPressRecognizer.view;
[cell setSelected:YES];
...
}
}