【问题标题】:How to apply multiple masks to UIView如何将多个掩码应用于 UIView
【发布时间】:2018-11-16 02:02:56
【问题描述】:

我有一个关于如何将多个掩码应用于已经有掩码的 UIView 的问题。

情况:
我有一个带有活动遮罩的视图,该遮罩在其左上角创建了一个孔,这是一个模板 UIView,可在项目中的任何地方重复使用。在项目的后期,我希望能够创建第二个孔,但这次是在右下角,无需创建全新的 UIView。

问题:
当我使用底部面膜时,它当然会替换第一个面膜,从而去除顶部孔......有没有办法将它们结合起来?就此而言,要将任何现有的面具与新的面具结合起来吗?

提前谢谢你!

【问题讨论】:

    标签: ios swift uiview mask cashapelayer


    【解决方案1】:

    这是我在项目中使用的代码,用于在 UIView 中创建一个圆形和一个矩形掩码,您可以将 UIBezierPath 行替换为相同的弧码:

    func createCircleMask(view: UIView, x: CGFloat, y: CGFloat, radius: CGFloat, downloadRect: CGRect){
        self.layer.sublayers?.forEach { ($0 as? CAShapeLayer)?.removeFromSuperlayer() }
    
        let mutablePath      = CGMutablePath()
        mutablePath.addArc(center: CGPoint(x: x, y: y + radius), radius: radius, startAngle: 0.0, endAngle: 2 * 3.14, clockwise: false)
        mutablePath.addRect(view.bounds)
        let path             = UIBezierPath(roundedRect: downloadRect, byRoundingCorners: [.topLeft, .bottomRight], cornerRadii: CGSize(width: 5, height: 5))
        mutablePath.addPath(path.cgPath)
    
        let mask             = CAShapeLayer()
        mask.path            = mutablePath
        mask.fillRule        = kCAFillRuleEvenOdd
        mask.backgroundColor = UIColor.clear.cgColor
    
    
        view.layer.mask      = mask
    }
    

    传递相同的 UIView,它会删除以前的图层并在相同的 UIView 上应用新的蒙版。

    这里mask.fillRule = kCAFillRuleEvenOdd 很重要。如果您注意到有 3 个mutablePath.addPath() 函数,kCAFillRuleEvenOdd 所做的是,它首先用圆弧创建一个孔,然后添加该视图边界的 Rect,然后添加另一个蒙版来创建第二个孔。

    【讨论】:

    • 非常感谢!尽管您的解决方案似乎删除并重新创建了所有形状,但我注意到在圆弧和路径之间添加了视图的矩形,这是我所缺少的!我添加了一个更全局的解决方案,它似乎可以工作,而无需知道以前的掩码是如何创建的!
    【解决方案2】:

    根据@Sharad 的回答,我意识到重新添加视图的矩形将使我能够将原始蒙版和新蒙版合二为一。

    这是我的解决方案:

    func cutCircle(inView view: UIView, withRect rect: CGRect) {
    
        // Create new path and mask
        let newMask = CAShapeLayer()
        let newPath = UIBezierPath(ovalIn: rect)
    
        // Create path to clip
        let newClipPath = UIBezierPath(rect: view.bounds)
        newClipPath.append(newPath)
    
        // If view already has a mask
        if let originalMask = view.layer.mask,
            let originalShape = originalMask as? CAShapeLayer,
            let originalPath = originalShape.path {
    
            // Create bezierpath from original mask's path
            let originalBezierPath = UIBezierPath(cgPath: originalPath)
    
            // Append view's bounds to "reset" the mask path before we re-apply the original
            newClipPath.append(UIBezierPath(rect: view.bounds))
    
            // Combine new and original paths
            newClipPath.append(originalBezierPath)
    
        }
    
        // Apply new mask
        newMask.path = newClipPath.cgPath
        newMask.fillRule = kCAFillRuleEvenOdd
        view.layer.mask = newMask
    }
    

    【讨论】:

    • 非常简单的解决方案...谢谢!对于那些想要矩形而不是圆形的人,只需更改为: let newPath = UIBezierPath(rect: rect)
    【解决方案3】:

    如果你不仅有“简单的形状”而且有实际的图层,你可以做如下的事情。其他视图,例如 UILabelUIImageView

    let maskLayer = CALayer()
    maskLayer.frame = viewToBeMasked.bounds
    maskLayer.addSublayer(self.imageView.layer)
    maskLayer.addSublayer(self.label.layer)
    
    viewToBeMasked.bounds.layer.mask = maskLayer
    

    所以基本上我只是创建一个 maskLayer,它包含所有其他视图的图层作为子图层,然后将其用作蒙版。

    【讨论】:

      猜你喜欢
      • 2012-07-17
      • 1970-01-01
      • 2013-07-27
      • 1970-01-01
      • 1970-01-01
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      相关资源
      最近更新 更多