【问题标题】:How do I create a UIView with a transparent circle inside (in swift)?如何创建一个内部带有透明圆圈的 UIView(快速)?
【发布时间】:2015-04-11 11:46:08
【问题描述】:

我想创建一个如下所示的视图:

我认为我需要的是带有某种遮罩的 uiview,我可以使用 UIBezierpath 制作圆形遮罩,但是我无法反转它以遮盖除圆圈之外的所有内容。我需要它作为视图的遮罩而不是填充层,因为我打算遮罩的视图上有 UIBlurEffect。最终目标是在我现有的视图之上为这个 UIView 设置动画以提供指导。

请注意,我使用的是 swift。有没有办法做到这一点?如果是这样,怎么做?

【问题讨论】:

标签: ios swift uiview uikit


【解决方案1】:

您可以使用此功能来创建您需要的内容。

func createOverlay(frame : CGRect)
{
    let overlayView = UIView(frame: frame)
    overlayView.alpha = 0.6
    overlayView.backgroundColor = UIColor.blackColor()
    self.view.addSubview(overlayView)

    let maskLayer = CAShapeLayer()

    // Create a path with the rectangle in it.
    var path = CGPathCreateMutable()

    let radius : CGFloat = 50.0
    let xOffset : CGFloat = 10
    let yOffset : CGFloat = 10

    CGPathAddArc(path, nil, overlayView.frame.width - radius/2 - xOffset, yOffset, radius, 0.0, 2 * 3.14, false)
    CGPathAddRect(path, nil, CGRectMake(0, 0, overlayView.frame.width, overlayView.frame.height))


    maskLayer.backgroundColor = UIColor.blackColor().CGColor

    maskLayer.path = path;
    maskLayer.fillRule = kCAFillRuleEvenOdd

    // Release the path since it's not covered by ARC.
    overlayView.layer.mask = maskLayer
    overlayView.clipsToBounds = true
}

调整radiusxOffsetyOffset来改变圆的半径和位置。

【讨论】:

  • 嗨拉克什!您的解决方案非常有帮助。我有一个小小的疑问。我在这个蒙面的黑色视图下方有一个按钮。我在按钮上制作了一个透明矩形,就像您在上述解决方案中所做的那样。但由于这个黑色视图在顶部,我无法点击按钮。有什么方法可以点击按钮吗?
  • @Abhishek729 - 您要确保将图层的 isUserInteractionEnabled 设置为 false 以单击它。
【解决方案2】:

对于 Swift 3,这是 rakeshbs 的答案格式,因此它返回所需的 UIView:

func createOverlay(frame : CGRect, xOffset: CGFloat, yOffset: CGFloat, radius: CGFloat) -> UIView
{
    let overlayView = UIView(frame: frame)
    overlayView.alpha = 0.6
    overlayView.backgroundColor = UIColor.black

    // Create a path with the rectangle in it.
    let path = CGMutablePath()
    path.addArc(center: CGPoint(x: xOffset, y: yOffset), radius: radius, startAngle: 0.0, endAngle: 2 * 3.14, clockwise: false)
    path.addRect(CGRect(x: 0, y: 0, width: overlayView.frame.width, height: overlayView.frame.height))

    let maskLayer = CAShapeLayer()
    maskLayer.backgroundColor = UIColor.black.cgColor
    maskLayer.path = path;
    maskLayer.fillRule = kCAFillRuleEvenOdd

    // Release the path since it's not covered by ARC.
    overlayView.layer.mask = maskLayer
    overlayView.clipsToBounds = true

    return overlayView
}

【讨论】:

  • 感谢 swift 3 的翻译!!很有帮助
【解决方案3】:

为 Swift 4 再次更新并删除了一些项目以使代码更紧凑。

请注意 maskLayer.fillRule 在 Swift 4 和 Swift 4.2 之间设置不同。

func createOverlay(frame: CGRect,
                   xOffset: CGFloat,
                   yOffset: CGFloat,
                   radius: CGFloat) -> UIView {
    // Step 1
    let overlayView = UIView(frame: frame)
    overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
    // Step 2
    let path = CGMutablePath()
    path.addArc(center: CGPoint(x: xOffset, y: yOffset),
                radius: radius,
                startAngle: 0.0,
                endAngle: 2.0 * .pi,
                clockwise: false)
    path.addRect(CGRect(origin: .zero, size: overlayView.frame.size))
    // Step 3
    let maskLayer = CAShapeLayer()
    maskLayer.backgroundColor = UIColor.black.cgColor
    maskLayer.path = path
    // For Swift 4.0
    maskLayer.fillRule = kCAFillRuleEvenOdd
    // For Swift 4.2
    maskLayer.fillRule = .evenOdd
    // Step 4
    overlayView.layer.mask = maskLayer
    overlayView.clipsToBounds = true

    return overlayView
}

对正在发生的事情的粗略分类:

  1. 创建一个大小为指定框架的视图,黑色背景设置为 60% 的不透明度
  2. 使用提供的起点和半径创建绘制圆的路径
  3. 为要移除的区域创建遮罩
  4. 将蒙版和剪辑应用于边界

下面的代码 sn-p 会调用它并在屏幕中间放置一个半径为 50 的圆:

let overlay = createOverlay(frame: view.frame,
                            xOffset: view.frame.midX,
                            yOffset: view.frame.midY,
                            radius: 50.0)
view.addSubview(overlay)

看起来像这样:

【讨论】:

    【解决方案4】:

    上述解决方案效果很好。

    如果你正在寻找带有矩形区域的面具,这里是下面的sn-p

    let fWidth = self.frame.size.width
    let fHeight = self.frame.size.height
    let squareWidth = fWidth/2
    let topLeft = CGPoint(x: fWidth/2-squareWidth/2, y: fHeight/2-squareWidth/2)
    let topRight = CGPoint(x: fWidth/2+squareWidth/2, y: fHeight/2-squareWidth/2)
    let bottomLeft = CGPoint(x: fWidth/2-squareWidth/2, y: fHeight/2+squareWidth/2)
    let bottomRight = CGPoint(x: fWidth/2+squareWidth/2, y: fHeight/2+squareWidth/2)
    let cornerWidth = squareWidth/4
    
    
    // Step 2
    let path = CGMutablePath()
    path.addRoundedRect(in: CGRect(x: topLeft.x, y: topLeft.y,
      width: topRight.x - topLeft.x, height: bottomLeft.y - topLeft.y),
     cornerWidth: 20, cornerHeight: 20)
    
    
    path.addRect(CGRect(origin: .zero, size: self.frame.size))
    // Step 3
    let maskLayer = CAShapeLayer()
    maskLayer.backgroundColor = UIColor.clear.cgColor
    maskLayer.path = path
    // For Swift 4.0
    maskLayer.fillRule = kCAFillRuleEvenOdd
    // For Swift 4.2
    //maskLayer.fillRule = .evenOdd
    // Step 4
    self.layer.mask = maskLayer
    self.clipsToBounds = true
    

    rectangle mask looks like this

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-17
      • 1970-01-01
      • 2014-12-26
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      • 1970-01-01
      • 2017-03-14
      相关资源
      最近更新 更多