Tableview上下文菜单:从行到预览视图控制器的自定义动画

问题描述 投票:0回答:2

我为一个tableview实现了特定于行的上下文菜单,其中包括一个简单的预览视图控制器,如下所示。

Screen recording showing context menu

我想实现过渡或动画,以使表视图中的图标(UIImageView)动画化为预览视图控制器中的图标。

但是,查看documentation(尤其是UITargetedPreviewUIPreviewTarget),我无法弄清楚如何在具有多行的表格视图的上下文中创建这样的动画。


[预览视图控制器是使用数据模型中的图标根据行生成的,如下所示:

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)
}
ios swift uitableview contextmenu
2个回答
1
投票

我认为实施协议UIViewControllerAnimatedTransitioning可以使您朝正确的方向发展。首先有点复杂。这是一个示例,如何执行此操作

https://github.com/dasdom/DDHCustomTransition/blob/master/DDHCustomTransition/Transition/CustomTransition.swift


0
投票

[article by Kyle Bashour,我无需进行详细的转换就找到了本机可可解决方案。

似乎在表视图中实现上下文菜单时,所有标准单视图上下文菜单UIContextMenuInteractionDelegate方法都具有等效的UITableViewDelegate方法。

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

Desired outcome screen capture

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

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

然后我必须实现这两个委托方法-都调用相同的代码块以返回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是我的自定义UIImageView中的UITableViewCell


[请注意,为了确保即使在显示菜单时更改表数据也要安全,Kyle建议使用带有索引路径的实际数据模型来获取预览所需的数据。有关更多信息,请参见他的文章。

© www.soinside.com 2019 - 2024. All rights reserved.