从 Swift 中的另一个 UIView 中减去 UIView

Subtract UIView from another UIView in Swift

我确信这是一件非常简单的事情,但我似乎无法理解其中的逻辑。

我有两个 UIView。一个黑色、半透明和 "full-screen" ("overlayView"),另一个在顶部,较小且可调整大小 ("cropView")。这几乎是一个裁剪视图设置,我想 "dim" 排除未裁剪的底层图像区域。

我的问题是:我该怎么做?我确定我的方法应该使用 CALayers 和蒙版,但无论我尝试什么,我都无法理解逻辑。

这是我现在拥有的:

这就是我想要的样子:

如何在 Swift 中获得此结果?

可能还有其他绘图解决方案,但基本上您有 4 个区域需要处理。取 space 上方和下方的正方形区域的全宽,并在它们之间添加左右两侧,并相互约束。

虽然您找不到subtract(...)这样的方法,但您可以使用以下代码轻松构建带有覆盖和透明切割的屏幕:

Swift 4.2

private func addOverlayView() {
    let overlayView = UIView(frame: self.bounds)
    let targetMaskLayer = CAShapeLayer()

    let squareSide = frame.width / 1.6
    let squareSize = CGSize(width: squareSide, height: squareSide)
    let squareOrigin = CGPoint(x: CGFloat(center.x) - (squareSide / 2),
                               y: CGFloat(center.y) - (squareSide / 2))
    let square = UIBezierPath(roundedRect: CGRect(origin: squareOrigin, size: squareSize), cornerRadius: 16)

    let path = UIBezierPath(rect: self.bounds)
    path.append(square)

    targetMaskLayer.path = path.cgPath
    // Exclude intersected paths
    targetMaskLayer.fillRule = CAShapeLayerFillRule.evenOdd

    overlayView.layer.mask = targetMaskLayer
    overlayView.clipsToBounds = true
    overlayView.alpha = 0.6
    overlayView.backgroundColor = UIColor.black

    addSubview(overlayView)
}

只需在自定义视图的构造函数或 ViewController 的 viewDidLoad().

中调用此方法

演练

首先我创建了一个原始的 overlayView,然后是我称之为 "targetMaskLayer" 的 CAShapeLayer。最终目标是在 overlayView 内借助 UIBezierPath 绘制一个正方形。定义正方形的尺寸后,我将其 cgPath 设置为 targetMaskLayer 的路径。

现在是重要的部分:

targetMaskLayer.fillRule = CAShapeLayerFillRule.evenOdd

这里我基本上配置了填充规则排除交集

最后,我为 overlayView 提供了一些样式并将其添加为子视图。

ps.: 别忘了import UIKit