在Swift中,将一个UIView作为另一个UIView的蒙版

8
我正在使用Swift和xCode开发应用程序。我的屏幕上有一个动物的图片(outlet为"backImage"),在这个图片上面我有一个视图(outlet为"coverView"),颜色为黑色,覆盖了整个屏幕。因此,您目前无法看到动物图片,因为"coverView"在它的前面。然后我有另一个视图(outlet为"maskView"),它比较小,并且覆盖在大视图"coverView"的上面。我想要的是将这个"maskView"作为遮罩,从而通过它看到"backImage",就像窗户一样。

有谁能够解决这个问题吗?

这是我的屏幕截图,我想要通过较小的白色视图看到灰色视图后面的女人角色:

enter image description here

2个回答

16
您可以从遮罩视图中设置alpha属性,并将其添加到其他视图的前面,例如:
let maskView = UIView()
maskView.backgroundColor = UIColor(white: 0, alpha: 0.5) //you can modify this to whatever you need
maskView.frame = CGRect(x: 0, y: 0, width: imageView.frame.width, height: imageView.frame.height)

yourView.addSubview(maskView)

编辑:现在我看到了你的问题图片,明白你的需求了。以下是实现方法。

func setMask(with hole: CGRect, in view: UIView){

    // Create a mutable path and add a rectangle that will be h
    let mutablePath = CGMutablePath()
    mutablePath.addRect(view.bounds)
    mutablePath.addRect(hole)

    // Create a shape layer and cut out the intersection
    let mask = CAShapeLayer()
    mask.path = mutablePath
    mask.fillRule = kCAFillRuleEvenOdd

    // Add the mask to the view
    view.layer.mask = mask

}

使用此函数时,您只需要拥有一个视图并创建一个形状,该形状将成为该视图中的一个孔,例如:
// Create the view (you can also use a view created in the storyboard)
let newView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
newView.backgroundColor = UIColor(white: 0, alpha: 1)

// You can play with these values and find one that fills your need
let rectangularHole = CGRect(x: view.bounds.width*0.3, y: view.bounds.height*0.3, width: view.bounds.width*0.5, height: view.bounds.height*0.5)

// Set the mask in the created view        
setMask(with: rectangularHole, in: newView)

嗨,Alexandre,我不确定我是否做得正确,但是它没有起作用。如果我正确理解了你的代码,你正在创建一个背景为白色0且透明度为0.5的UIView,然后定义大小并添加到我的大视图下面。问题在于我想要看到的是在大视图的后面,因此这个新的UIView必须在我的大视图中开一个洞。感谢你的帮助! - DevRenanGaspar
我现在已经连接了我的屏幕。 - DevRenanGaspar
@DevRenanGaspar 现在我看到了图片,我想我知道你需要什么,所以我编辑了我的答案。 - Alexandre Lara
你是最棒的!非常感谢。它运行得非常好!只需要做一个小改变,可以使用我的故事板中的视图作为 rectangularHole,而不是像你所编码创建的那样。我知道我可以用我的 SB 中的视图替换你创建的 newView,我理解了这一点,我也确实这样做了。但是我能否对孔做同样的操作呢?再次感谢! - DevRenanGaspar
我想我明白了!真不敢相信,花了太多小时才解决这个问题... 我用CGRect替换了创建rectangularHole的方法,写成了"let rectangularHole = windowView.frame.integral"... 如果你有其他更好的办法,请告诉我,但这个方法确实有效!谢谢! - DevRenanGaspar
@DevRenanGaspar 不用谢。我已经有一段时间没有使用storyboards了,所以我真的不知道我是否会使用不同的方式,但是如果你的方法有效,那就太好了。祝你编码愉快! - Alexandre Lara

0

谢谢,@Alexandre Lara!你做到了!

以下是解决方案:

@IBOutlet weak var windowView: UIView!
@IBOutlet weak var bigCoverView: UIView!

func setMask(with hole: CGRect, in view: UIView){

    // Create a mutable path and add a rectangle that will be h
    let mutablePath = CGMutablePath()
    mutablePath.addRect(view.bounds)
    mutablePath.addRect(hole)

    // Create a shape layer and cut out the intersection
    let mask = CAShapeLayer()
    mask.path = mutablePath
    mask.fillRule = kCAFillRuleEvenOdd

    // Add the mask to the view
    view.layer.mask = mask

}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let rectangularHole = windowView.frame.integral

    // Set the mask in the created view
    setMask(with: rectangularHole, in: bigCoverView!)

}

嗨@DevRenanGaspar,我在我的项目中有同样的要求。我已经使用了您发布的上述代码。它不能满足我的需求。请帮助我提供一些示例应用程序或更多解释。谢谢。 - Narasimha Nallamsetty

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