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

4
我相信这是一件非常简单的事情,但我似乎无法理解其逻辑。
我有两个UIView。一个是黑色、半透明的“全屏”叠加视图(“overlayView”),另一个在顶部,较小且可调整大小(“cropView”)。它基本上是一个裁剪视图设置,在其中我想要“暗淡”下不被裁剪的底层图像区域。
我的问题是:我该怎么做?我确定我的方法应该使用CALayer和遮罩,但无论我尝试什么,都无法理解其逻辑。
这是我现在拥有的:
这是我想要的:
我如何在Swift中实现这个结果?

展示你目前所拥有的代码。 - Wain
没有太多的代码可以展示。基本上只有两个简单的视图,一个在另一个上面,具有不同的框架大小。 - schnabler
你尝试过使用遮罩或在叠加层中绘制路径吗? - Wain
是的,这就是我做的,但是那些代码都没用,所以我把它们删除了。就像我说的那样,我似乎无法理解图层和遮罩背后的逻辑 -> 即视图层次结构,什么是遮罩等。 - schnabler
这个想法是你展示代码,我们来修复它;-) 你想要的是一个带有背景颜色的全尺寸层(这是覆盖视图层),以及一个中间透明的遮罩层。 - Wain
2个回答

5

虽然你找不到像 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)
}

只需在自定义视图的构造函数中或在视图控制器的 viewDidLoad() 中调用此方法。

步骤

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

现在是一个重要的部分:

targetMaskLayer.fillRule = CAShapeLayerFillRule.evenOdd

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

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

ps:不要忘记导入 UIKit。


1

可能有其他的绘图解决方案,但基本上你需要处理4个区域。取上下空间的正方形区域,并在它们之间添加右侧和左侧的约束条件。


我曾考虑过这样做,但感觉这很不优雅。我希望能使用掩码得出更为优秀的解决方案。 - schnabler
好吧,这个解决方案似乎不太优雅,但另一种解决方案是制作一个带有中心部分的图像,然后进行色调效果处理,并将图像放回顶部。这种解决方案的缺点是您需要自己实现所有绘图,而例如scrollview可以完美地处理缩放、滑动等操作。任何使用CALayer进行绘图的操作都需要相同的逻辑。 - Christian
好的,这很好地运作并且似乎没有任何缺点。谢谢! - schnabler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接