Подтвердить что ты не робот

Простой способ показать всплывающее окно "Копировать" на UITableViewCells, например, приложение адресной книги

Есть ли простой способ для подклассов UITableViewCell отображать всплывающее окно "Копировать" UIMenuController, как в приложении "Адресная книга" (см. снимок экрана) после того, как выбор удерживается некоторое время?

address book

4b9b3361

Ответ 1

Метод до iOS 5 состоит в том, чтобы получить общий экземпляр UIMenuController, установить целевой прямоangularьник и просмотреть и вызвать -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; 

Ответ 2

В настоящее время существует официальный интерфейс для отображения меню ячейки 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. [ EDIT. Поскольку это было опубликовано, я узнал, как добавлять пользовательские пункты меню.]

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

Ответ 3

Вот синтаксис 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
    }
}

Ответ 4

Подкласс 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];
}

Ответ 5

 #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];
    }
}

Ответ 6

Для предварительной iOS13 см. Александр ответ. Для iOS13 shouldShowMenuForRowAt и canPerformAction устарели, поэтому вы должны использовать следующий 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. при длительном нажатии на ячейку пользовательский интерфейс не будет отображаться ниже, это будет старый пользовательский интерфейс, который немного противоречив.

enter image description here