ios - 表格 View 上下文菜单 : custom animation from row to a preview view controller

标签 ios swift uitableview contextmenu

我已经为表格 View 实现了特定于行的上下文菜单,其中包括一个简单的预览 View Controller ,如下所示。

Screen recording showing context menu

我想实现一个转换或动画,以便 TableView 中的图标(UIImageView)动画到预览 View Controller 中的图标的位置。

但是,看看 documentation (特别是 UITargetedPreviewUIPreviewTarget),我不知道如何在多行的 tableview 上下文中创建这样的动画。


预览 View Controller 是根据行使用数据模型中的图标生成的,如下所示:

class DrugPreviewViewController: UIViewController {
    private let imageView = UIImageView()

    override func loadView() {
        view = imageView
    }

    init(item: CustomItem) {
        super.init(nibName: nil, bundle: nil)

        // Set up image view
        imageView.clipsToBounds = true
        imageView.contentMode = .scaleAspectFill
        imageView.backgroundColor = .clear
        imageView.image = UIImage(named: item.icon ?? "defaultIcon")?.withRenderingMode(.alwaysTemplate).tinted(with: Color.colors[item.iconBackgroundColor ?? 0])
        // Preview to have the same aspect ratio as the image
        preferredContentSize = UIImage(named: item.icon ?? "defaultIcon")!.size
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

缩短的上下文菜单代码如下所示:

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

    // Selected Drug and notes
    let selectedItem: CustomItem = dataArray[indexPath.row]

    var notes = selectedItem.notes ?? ""
    var titleString = selectedItem.name

    // Code for menu items and actions
    // Defines actions array
    // Omitted for brevity

    let actionProvider: UIContextMenuActionProvider = { _ in
        return UIMenu(title: titleString, children: actions)
    }

    return UIContextMenuConfiguration(identifier: indexPath as NSCopying, previewProvider: {
        return CustomPreviewViewController(item: selectedItem)
    }, actionProvider: actionProvider)
}

最佳答案

感谢 article by Kyle Bashour,我找到了一个原生的 Cocoa 解决方案,而无需自己进行详细的转换。 .

当您在 TableView 中实现上下文菜单时,似乎所有标准单 View 上下文菜单 UIContextMenuInteractionDelegate 方法都具有等效的 UITableViewDelegate 方法。

我设法实现了如下所示的结果。它不会将图标动画化到中间的预览中,但它足够接近我想要的,并且看起来比我以前的要好得多。

Desired outcome screen capture

为了实现这一点,我需要在上面返回上下文菜单的代码中将 previewProvider 设置为 nil:

return UIContextMenuConfiguration(identifier: indexPath as NSCopying, previewProvider: nil, actionProvider: actionProvider)

然后我必须实现这两个委托(delegate)方法 - 两者都调用相同的代码块来返回 UITargetedPreview:

@available(iOS 13.0, *)
override func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
    return makeTargetedPreview(for: configuration)
}


@available(iOS 13.0, *)
override func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
    return makeTargetedPreview(for: configuration)
}

@available(iOS 13.0, *)
private func makeTargetedPreview(for configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
    guard let indexPath = configuration.identifier as? IndexPath else { return nil }
    // Get the cell for the index of the model
    guard let cell = tableView.cellForRow(at: indexPath) as? DrugTableViewCell else { return nil }
    // Set parameters to a circular mask and clear background
    let parameters = UIPreviewParameters()
    parameters.backgroundColor = .clear
    parameters.visiblePath = UIBezierPath(ovalIn: cell.iconView.bounds)

    // Return a targeted preview using our cell previewView and parameters
    return UITargetedPreview(view: cell.iconView, parameters: parameters)
}

cell.iconView 是我的自定义 UITableViewCell 中的 UIImageView


请注意,为了确保在显示菜单时表格数据发生变化时的安全,Kyle 建议使用实际数据模型(通过索引路径访问)来获取预览所需的数据(而不是单元格) )。请参阅他的文章了解更多信息。

关于ios - 表格 View 上下文菜单 : custom animation from row to a preview view controller,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59444558/

相关文章:

swift - 方法无法标记为@objc,因为参数 3 的类型无法在 Objective-C 中表示 - @objc func 中无法识别错误类型?

ios - 当用户单击该部分的一行时访问 TableView 中的部分标题按钮?

objective-c - 根据 Apple 指南,将文件保存到哪个目录?

来自不同网络的 iOS GameCenter 连接

ios - Swift/NSMutableDisctionary init/如何使值可选

ios - 在 Swift 中的 Controller 之间传递数据

ios - UITableView 使用 UIRefreshControl 闪烁

objective-c - 从 Objective C 中的文件读取

ios - 段落最后两行之间的间距更大?

xcode - swift 1.2 更新 Parse.com 的查询错误