Простой способ показать всплывающее окно «Копировать» на UITableViewCells, как приложение адресной книги - PullRequest
36 голосов
/ 21 марта 2010

Есть ли простой способ для подклассов UITableViewCell показывать всплывающее окно UIMenuController «Копировать», как в приложении «Адресная книга» (см. Скриншот), после того, как выбор удерживается некоторое время?1004 *

Ответы [ 5 ]

38 голосов
/ 10 ноября 2011

Теперь есть официальный интерфейс для отображения меню ячеек UITableView в iOS 5. Пример (из делегата таблицы):

- (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 не помогло;Я не смог отобразить свой пользовательский пункт меню.Из моих экспериментов похоже, что поддерживаются только Copy, Cut и Paste.[ РЕДАКТИРОВАТЬ С тех пор, как это было опубликовано, я научился добавлять пользовательские пункты меню.]

Обратите внимание, что это работает, только если реализованы все три метода делегата.

28 голосов
/ 21 марта 2010

Метод перед iOS 5 состоит в том, чтобы получить общий экземпляр UIMenuController, установить целевой прямоугольник, просмотреть и вызвать -setMenuVisible:animated:. Запомните, чтобы включить -canPerformAction:withSender: в вашем респондере.


Метод после iOS 5 (ранее доступный как недокументированная функция) заключается в реализации этих трех методов в вашем источнике данных (см. 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; 
21 голосов
/ 31 марта 2016

Вот синтаксис 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
    }
}
14 голосов
/ 23 марта 2010

Ваш подкласс 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];
}
10 голосов
/ 26 января 2015
 #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];
    }
}
...