UIDragInteractionDelegate:如何在dragInteraction返回的拖动预览中显示透明部分(_:previewForLifting:session:)

Posted

技术标签:

【中文标题】UIDragInteractionDelegate:如何在dragInteraction返回的拖动预览中显示透明部分(_:previewForLifting:session:)【英文标题】:UIDragInteractionDelegate: How to display transparent parts in the drag preview returned by dragInteraction(_:previewForLifting:session:) 【发布时间】:2018-04-16 06:10:21 【问题描述】:

我正在为 ios 应用构建 drag and drop 交互。我想让用户能够拖放包含透明部分的图像。

但是,拖拽内容的默认预览是一个带有不透明白色背景的矩形,覆盖了我的应用程序的背景。

当我通过实现 UIDragInteractionDelegate 方法创建自定义预览时 dragInteraction(_:previewForLifting:session:),就像Apple的代码示例Adopting Drag and Drop in a Custom View一样,我的源图像的透明度仍然没有考虑在内,这意味着我的预览图像仍然显示在一个不透明的白色背景的矩形中:

func dragInteraction(_ interaction: UIDragInteraction, previewForLifting item: UIDragItem, session: UIDragSession) -> UITargetedDragPreview? 
    guard let image = item.localObject as? UIImage else  return nil 

    // Scale the preview image view frame to the image's size.
    let frame: CGRect
    if image.size.width > image.size.height 
        let multiplier = imageView.frame.width / image.size.width
        frame = CGRect(x: 0, y: 0, width: imageView.frame.width, height: image.size.height * multiplier)
     else 
        let multiplier = imageView.frame.height / image.size.height
        frame = CGRect(x: 0, y: 0, width: image.size.width * multiplier, height: imageView.frame.height)
    

    // Create a new view to display the image as a drag preview.
    let previewImageView = UIImageView(image: image)
    previewImageView.contentMode = .scaleAspectFit
    previewImageView.frame = frame

    /*
         Provide a custom targeted drag preview that lifts from the center
         of imageView. The center is calculated because it needs to be in
         the coordinate system of imageView. Using imageView.center returns
         a point that is in the coordinate system of imageView's superview,
         which is not what is needed here.
     */
    let center = CGPoint(x: imageView.bounds.midX, y: imageView.bounds.midY)
    let target = UIDragPreviewTarget(container: imageView, center: center)
    return UITargetedDragPreview(view: previewImageView, parameters: UIDragPreviewParameters(), target: target)

我试图强制预览不透明,但没有帮助:

previewImageView.isOpaque = false

如何在电梯预览中获得透明部分?

【问题讨论】:

【参考方案1】:

覆盖UIDragPreviewParameters 中的backgroundColor,因为它定义了拖动项目预览的背景颜色

将其设置为UIColor.clear,这是一个灰度和alpha值都是0.0的颜色对象

let previewParameters = UIDragPreviewParameters()
previewParameters.backgroundColor = UIColor.clear // transparent background
return UITargetedDragPreview(view: previewImageView,
                             parameters: previewParameters,
                             target: target)

【讨论】:

透明但有点不透明对我来说不够 @MichałZiobro 您可以根据您的图像定义一个UIBezierPath,并将其设置为previewParameters.visiblePath【参考方案2】:

你可以根据你的图片定义一个UIBezierPath,设置为previewParameters.visiblePath

示例(Swift 4.2):

let previewParameters = UIDragPreviewParameters()
previewParameters.visiblePath = UIBezierPath(roundedRect: CGRect(x: yourX, y: yourY, width: yourWidth, height: yourHeight), cornerRadius: yourRadius)
//... Use the created previewParameters

【讨论】:

这实际上是最好和最干净的方法。当您的单元格没有来自内容本身的填充(例如子视图)时,UIColor.clear 起作用 这是正确的解决方案。使用 backgroundColor = .clear 会导致阴影出现奇怪的 UI 故障。

以上是关于UIDragInteractionDelegate:如何在dragInteraction返回的拖动预览中显示透明部分(_:previewForLifting:session:)的主要内容,如果未能解决你的问题,请参考以下文章