UITableViewCell 選択時にメニューを表示する
前回は UITableViewDelegate
を使って簡単にメニュー表示をする方法について書いた。
この方法はセルを長押しした時にメニューを表示する事ができるが、セルをタップして選択したらすぐにメニューを表示したい場合がある。
この場合は前回紹介した
- tableView:shouldShowMenuForRowAtIndexPath:
- tableView:canPerformAction:forRowAtIndexPath:withSender:
- tableView:performAction:forRowAtIndexPath:withSender:
これらの UITableViewDelegate
のメソッドを使わないで、セルの選択時に直接コードで UIMenuController
を表示するよう実装する。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UIMenuController *menuController = [UIMenuController sharedMenuController]; CGRect rect = [tableView rectForRowAtIndexPath:indexPath]; [menuController setTargetRect:rect inView:tableView]; [menuController setMenuVisible:YES animated:YES]; }
それぞれ実行したいメソッド copy: paste: cut: も実装する。
実装内容は前回と全く同じコード
- (void)copy:(id)sender { NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow; // copy content to pasteboard NSString *string = self.list[indexPath.row]; [UIPasteboard generalPasteboard].string = string; } - (void)paste:(id)sender { NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow; // retrieve content from pasteboard NSString *string = [UIPasteboard generalPasteboard].string; // replace content in list self.list[indexPath.row] = string; // configure tableview [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; } - (void)cut:(id)sender { NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow; // copy content to pasteboard NSString *string = self.list[indexPath.row]; [UIPasteboard generalPasteboard].string = string; // delete content from list [self.list removeObjectAtIndex:indexPath.row]; // configure tableview [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; }
そして重要、というか忘れやすいのが
- (BOOL)canBecomeFirstResponder { return YES; }
これを実装して ViewController が firstResponder になれるようにする事。
これをしないとメニューが表示されない。
あと最後に、
これらの実装だけだとメニュー表示がキャンセルされた時にセルの選択状態が解除されないという現象が起きるので、メニューが非表示になる際にセルを deselect する。
メニューが非表示になるタイミングは UIMenuControllerWillHideMenuNotification
を使って通知を受け取る事ができる。
全体の実装は以下
いい感じに実装できた。
関連