42

UITableViewCellのサブクラスが、選択がしばらく保持された後、アドレス帳アプリ(スクリーンショットを参照)のように「コピー」UIMenuControllerポップアップを表示する簡単な方法はありますか?

住所録
(出典:icog.net

4

7 に答える 7

42

iOS 5でUITableViewセルメニューを表示するための公式インターフェイスが追加されました。例(テーブルデリゲートから):

- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
    return (action == @selector(copy:));
}

- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
    if (action == @selector(copy:)){
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        [[UIPasteboard generalPasteboard] setString:cell.textLabel.text];
    }
}

UIMenuControllerの共有コントローラーを変更して独自のメニュー項目を追加しようとしましたが、それを追加してcanPerformActionメッセージを受け取ることができましたが、YESを返すことは役に立ちませんでした。カスタムメニュー項目を表示できませんでした。私の実験からは、コピー、切り取り、貼り付けのみがサポートされているようです。[編集これが投稿されてから、カスタムメニュー項目を追加する方法を学びました。]

これは、3つのデリゲートメソッドすべてが実装されている場合にのみ機能することに注意してください。

于 2011-11-09T20:43:08.920 に答える
31

iOS 5より前の方法は、UIMenuControllerの共有インスタンスを取得し、ターゲットrectを設定し、を表示して呼び出すこと-setMenuVisible:animated:です。レスポンダーに実装することを忘れない-canPerformAction:withSender:でください。


iOS 5以降の方法(以前は文書化されていない機能として利用可能)は、これら3つの方法をデータソースに実装することです(https://developer.apple.com/reference/uikit/uitableviewdelegate#1653389を参照)。

-(void)tableView:(UITableView*)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath*)indexPath withSender:(id)sender;
-(BOOL)tableView:(UITableView*)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath*)indexPath withSender:(id)sender;
-(BOOL)tableView:(UITableView*)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath*)indexPath; 
于 2010-03-21T18:39:45.033 に答える
30

をコピーするためのSwift構文は次のとおりですdetailTextLabel

func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
    return (tableView.cellForRow(at: indexPath)?.detailTextLabel?.text) != nil
}

func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
    return action == #selector(copy(_:))
}

func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {
    if action == #selector(copy(_:)) {
        let cell = tableView.cellForRow(at: indexPath)
        let pasteboard = UIPasteboard.general
        pasteboard.string = cell?.detailTextLabel?.text
    }
}
于 2016-03-31T07:58:22.750 に答える
14

UITableViewCellサブクラスは次のようになります

@interface MenuTableViewCell : UITableViewCell {
}
- (IBAction)copy:(id)sender;
- (void)showMenu;

@end


@implementation MenuTableViewCell

- (BOOL)canBecomeFirstResponder {
    return YES;
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(copy:)) {
        return YES;
    }
    return NO;
}
- (IBAction)copy:(id)sender {
}
- (void)showMenu {
    [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES];
    [self becomeFirstResponder];
    [[UIMenuController sharedMenuController] update];
    [[UIMenuController sharedMenuController] setTargetRect:CGRectZero inView:self];
    [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];

}

@end

そして、UITableViewデリゲートメソッドは次のようなものです

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    MenuTableViewCell *cell = (MenuTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[MenuTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell.
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    MenuTableViewCell *cell = (MenuTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
    [cell showMenu];
}
于 2010-03-23T01:29:52.740 に答える
10
 #pragma mark - COPY/PASTE Cell Text via Menu

- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
    return (action == @selector(copy:));
}

- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
    if (action == @selector(copy:))
    {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];
        [pasteBoard setString:cell.textLabel.text];
    }
}
于 2015-01-26T20:35:36.430 に答える
2

iOS13より前のバージョンについては、Alexanderの回答を参照してください。iOS13の場合shouldShowMenuForRowAtcanPerformAction非推奨であるため、次のAPIを使用する必要があります。

@available(iOS 13.0, *)
override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {

    return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { suggestedActions in

        return self.makeContextMenu(for: indexPath)
    })
}

@available(iOS 13.0, *)
func makeContextMenu(for indexPath: IndexPath) -> UIMenu {

    let copyAction = UIAction(title: "Copy") { [weak self] _ in
        guard let self = self else { return }
        let cell = self.tableView.cellForRow(at: indexPath)
        let pasteboard = UIPasteboard.general
        pasteboard.string = cell?.detailTextLabel?.text

    }

    // Create and return a UIMenu with the share action
    return UIMenu(title: "Options", children: [copyAction])
}

注:最終結果は異なります。しかし、これはAppleが提供しているすぐに使える機能です。ただし、iOS 13 Sim >> General>>Aboutの設定アプリを確認してください。セルを長押しすると、以下のUIは表示されません。古いUIになり、少し一貫性がなくなります。

ここに画像の説明を入力してください

于 2019-10-16T18:53:11.337 に答える
1

アレクサンダーのコードから2つのシナリオを作成しました:

1.detailTextLabelではなくtextLabelをコピーする場合は、次のコードを使用してください。

//MARK: Delegate
func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
    return (tableView.cellForRow(at: indexPath)?.textLabel?.text) != nil
}

func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
    return action == #selector(copy(_:))
}

func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {
    if action == #selector(copy(_:)) {
        let cell = tableView.cellForRow(at: indexPath)
        let pasteboard = UIPasteboard.general
        pasteboard.string = cell?.textLabel?.text
    }
}

2. customLabelsを含むcustomCellがあり、すべてのcustomLabelsテキストをコピーする場合これを実行します。

//MARK: Delegate
func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {

    return (tableView.cellForRow(at: indexPath) != nil)
}

func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
    return action == #selector(copy(_:))
}

func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {

    if action == #selector(copy(_:)) {

        /* change these array names according to your own array names */
        let customlabel1 = customlabel1Array[indexPath.row]     
        let customlabel2 = customlabel2Array[indexPath.row]
        let customlabel3 = customlabel3Array[indexPath.row]


        let pasteboard = UIPasteboard.general
        pasteboard.string = "\(customlabel1)\n\(customlabel2)\n\(customlabel3)"     /*    \n is for new line.   */
    }
}

}

ちなみに、これらを機能させるには、次のように、viewDidLoadでtableViewデリゲートをselfに設定する必要があります。

 override func viewDidLoad() {
  yourTableView.delegate = self
   }
于 2020-04-01T17:07:47.027 に答える