【问题标题】:Subtract UIView from another UIView in Swift从 Swift 中的另一个 UIView 中减去 UIView
【发布时间】:2015-05-17 14:23:06
【问题描述】:

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

我有两个 UIView。一个黑色、半透明和“全屏”(“overlayView”),另一个在顶部,较小且可调整大小(“cropView”)。这几乎是一种裁剪视图设置,我想在其中“变暗”未裁剪的底层图像区域。

我的问题是:我该怎么做?我确定我的方法应该使用 CALayers 和掩码,但无论我尝试什么,我都无法落后于逻辑。

这就是我现在拥有的:

这就是我想要的样子:

如何在 Swift 中实现这个结果?

【问题讨论】:

  • 显示您当前拥有的代码
  • 没有多少代码可以展示。它几乎只是两个简单的视图,它们具有不同的帧大小。
  • 那么您是否尝试过使用蒙版或在叠加层中绘制路径?
  • 是的,我就是这样做的,但是没有一个代码起作用,所以我把它去掉了。就像我说的,我似乎无法掌握图层和掩码背后的逻辑 -> 即视图的层次结构、被掩码的内容等。
  • 这个想法是您显示代码,我们会考虑修复它;-) 您想要一个带有背景颜色的全尺寸层(这是覆盖视图层)和一个遮罩层中间是透明的

标签: ios swift calayer mask


【解决方案1】:

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

【讨论】:

  • 我曾想过这样做,但这似乎很脏。我希望有一个更优雅的使用面具的解决方案。
  • 好吧,它看起来不那么优雅,但另一种解决方案是制作带有中心部分的图像,然后制作色调效果并在其顶部添加图像。该解决方案的缺点是您需要自己实现所有绘图,而滚动视图正在完美地处理缩放、滑动等。任何使用 CALayer 的绘图都需要相同的逻辑。
  • 好吧,这很好用,似乎没有缺点。谢谢!
【解决方案2】:

虽然你不会找到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。最终目标是在 UIBezierPath 的帮助下在该 overlayView 内绘制一个正方形。定义正方形的尺寸后,我将其cgPath 设置为targetMaskLayer 的路径。

现在是一个重要的部分:

targetMaskLayer.fillRule = CAShapeLayerFillRule.evenOdd

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

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

ps.:别忘了import UIKit

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-14
    • 2017-09-25
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    相关资源
    最近更新 更多